二进制数据帧到字典



嗨,我正在尝试使用python将数据帧转换为字典。该数据帧类似于:

data_quim = {'Type':[1,2,3],'BCN':['X',np.nan,np.nan],'MAD':[np.nan,'X',np.nan],'MAT':['X',np.nan,'X']}
df = pd.DataFrame(data_quim)
df
Type     BCN MAD MAT
0   1        X  NaN X
1   2       NaN X   NaN
2   3       NaN NaN X

我想买一本这样的字典:

{1:['BCN','MAT],
2:['MAD],
3:['MAT]}

我尝试了to_dict()函数,将第一个"类型"设置为索引,但无法得到我想要的。任何想法吗?

您可以使用:

(df.set_index('Type').stack()
.reset_index(1)
['level_1'].groupby(level=0)
.apply(list)
.to_dict()
)

输出:

{1: ['BCN', 'MAT'], 2: ['MAD'], 3: ['MAT']}

或者,使用apply:

(df.set_index('Type')
.apply(lambda s: list(s.dropna().index), axis=1)
.to_dict()
)

我真的很喜欢@mozway对这个特定问题的第二个答案,但是apply有时不是最快的。由于pandas是如此灵活,你也可以用pd.melt来做到这一点,这是一种非常灵活的方式,可以将宽数据转换为窄数据,并依赖groupby。如果您需要在将其放入列表之前使用更多条件/处理执行某些操作(如果您有'X','Y','NaN',并希望对'X'和'Y'执行不同的操作),这将更有帮助:

df.melt(id_vars='Type')
.dropna()
.groupby('Type')
.agg({'variable': list})
.to_dict()['variable']

或者如果你出于某种原因想尽快离开熊猫:

{
row[0]: [
label 
for label, indicator in zip(df.columns[1:], row[1:]) 
if indicator == 'X'
] 
for row in df.values
}

总的来说,这是一个很好的问题,可以将原始宽表映射到每个'X'的键值对,然后通过键将所有值减少到一个列表中。由于您的行已经按键分组,所以我非常喜欢@mozway的第二个建议。我的第二个建议是在pandas之外完成它,如果您需要为每一行使用流迭代器,它也会工作得很好。