pandas:来自dict的数据帧,逗号分隔值为

时间:2016-08-28 15:56:59

标签: python pandas dataframe

我尝试从嵌套字典创建一个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

感谢任何帮助。感谢

2 个答案:

答案 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