我尝试从嵌套字典创建一个DataFrame,其中值以逗号分隔的字符串形式。
每个值都嵌套在一个dict中,例如:
dict = {"1":{
"event":"A, B, C"},
"2":{
"event":"D, B, A, C"},
"3":{
"event":"D, B, C"}
}
我想要的输出是:
A B C D
0 A B C NaN
1 A B C D
2 NaN B C D
到目前为止我所有人都将dict转换为dataframe并拆分每个列表中的项目。但我不确定这是否让我更接近我的目标。
df = pd.DataFrame(dict)
Out[439]:
1 2 3
event A, B, C D, B, A, C D, B, C
In [441]: df.loc['event'].str.split(',').apply(pd.Series)
Out[441]:
0 1 2 3
1 A B C NaN
2 D B A C
3 D B C NaN
感谢任何帮助。感谢
答案 0 :(得分:2)
您可以使用一些理解来按摩嵌套字典,以更好的格式创建DataFrame,以标记列的条目是否存在:
the_dict = {"1":{
"event":"A, B, C"},
"2":{
"event":"D, B, A, C"},
"3":{
"event":"D, B, C"}
}
df = pd.DataFrame([[{z:1 for z in y.split(', ')} for y in x.values()][0] for x in the_dict.values()])
>>> df
A B C D
0 1.0 1 1 NaN
1 1.0 1 1 1.0
2 NaN 1 1 1.0
一旦你创建了DataFrame,你就可以简单地循环遍历列,并使用where
方法将标记字母存在的值转换为字母(在NaN离开时,NaN会离开NaN) ,否则它会插入列的字母):
for col in df.columns:
df_mask = df[col].isnull()
df[col]=df[col].where(df_mask,col)
>>> df
A B C D
0 A B C NaN
1 A B C D
2 NaN B C D
根据@ merlin的建议,你可以直接理解答案:
df = pd.DataFrame([[{z:z for z in y.split(', ')} for y in x.values()][0] for x in the_dict.values()])
>>> df
A B C D
0 A B C NaN
1 A B C D
2 NaN B C D
答案 1 :(得分:1)
根据您所拥有的内容(修改了一点点拆分以去除多余的空格)df1
,您可能只需stack
结果并在索引和值列上使用pd.crosstab()
:
df1 = df.loc['event'].str.split('\s*,\s*').apply(pd.Series)
df2 = df1.stack().rename('value').reset_index()
pd.crosstab(df2.level_0, df2.value)
# value A B C D
# level_0
# 1 1 1 1 0
# 2 1 1 1 1
# 3 0 1 1 1
这不完全符合你的要求,但我想你可能更喜欢这个你想要的输出。
要获得您正在寻找的内容,您可以添加一个额外的列,该列等于上面的值列,然后将包含值的索引取消堆栈:
df2 = df1.stack().rename('value').reset_index()
df2['value2'] = df2.value
df2.set_index(['level_0', 'value']).drop('level_1', axis = 1).unstack(level = 1)
# value2
# value A B C D
# level_0
# 1 A B C None
# 2 A B C D
# 3 None B C D