【问题标题】:Populating a pandas dataframe from an odd dictionary从奇数字典中填充熊猫数据框
【发布时间】:2019-05-31 04:16:10
【问题描述】:

我有一本字典如下:

{'header_1': ['body_1', 'body_3', 'body_2'],
 'header_2': ['body_6', 'body_4', 'body_5'],
 'header_4': ['body_7', 'body_8'],
 'header_3': ['body_9'],
 'header_9': ['body_10'],
 'header_10': []}

我想提出一个这样的数据框:

+----+----------+--------+
| ID | header   | body   |
+----+----------+--------+
| 1  | header_1 | body_1 |
+----+----------+--------+
| 2  | header_1 | body_3 |
+----+----------+--------+
| 3  | header_1 | body_2 |
+----+----------+--------+
| 4  | header_2 | body_6 |
+----+----------+--------+
| 5  | header_2 | body_4 |
+----+----------+--------+
| 6  | header_2 | body_5 |
+----+----------+--------+
| 7  | header_4 | body_7 |
+----+----------+--------+

空白项(例如上面字典中的键header_10)将收到None 的值。我为df.loc 尝试了多种变体,例如:

for header_name, body_list in all_unique.items():
    for body_name in body_list:
        metadata.loc[metadata.index[-1]] = [header_name, body_name]

无济于事。当然,Pandas 中必须有一种快速的方法来追加行并自动增加索引?类似于仅使用 Python 代码的 SQL INSERT INTO 语句?

【问题讨论】:

  • 如果您只是将字典转换成 pandas 可以事先处理的内容会怎样?
  • 你不觉得这样效率低吗?它会引入额外的代码......
  • 比在每一步都尝试重新分配整个数据帧效率更低?因为这就是附加到它的作用。
  • 为了比较,你有字典,它是一种专门设计用于高效变异的数据结构。更多的代码并不意味着更低的代码效率。
  • @W-B 我会再次发布该答案。这正是我所需要的

标签: python-3.x pandas dictionary


【解决方案1】:

这又是一个unnesting 问题

借用 Jez 为您的 d 设置的设置

d = {k: v if bool(v) else [None] for k, v in d.items()}

第一次将你的字典转换成数据框

df=pd.Series(d).reset_index()
df.columns
Out[204]: Index(['index', 0], dtype='object')

然后在here中使用这个函数

yourdf=unnesting(df,[0])
yourdf
Out[208]: 
         0      index
0   body_1   header_1
0   body_3   header_1
0   body_2   header_1
1   body_6   header_2
1   body_4   header_2
1   body_5   header_2
2   body_7   header_4
2   body_8   header_4
3   body_9   header_3
4  body_10   header_9
5     None  header_10

def unnesting(df, explode):
    idx=df.index.repeat(df[explode[0]].str.len())
    df1=pd.concat([pd.DataFrame({x:np.concatenate(df[x].values)} )for x in explode],axis=1)
    df1.index=idx
    return df1.join(df.drop(explode,1),how='left')

【讨论】:

  • @jezrael 好的,让我删除我的答案
  • 我认为这个答案仍然很有价值,因为它显示了另一种方法。但我更喜欢@jezrael 的方法,因为它需要更少的代码行
  • @user32882 别担心,他的回答肯定更好
【解决方案2】:

如果数据集太大,这个解决方案会很慢,但它应该仍然有效。

for key in data.keys():
    vals= data[key]
    # Create temp df with data from a single key
    t_df = pd.DataFrame({'header':[key]*len(vals),'body':vals})

    # Append it to your full dataframe.
    df = df.append(t_df)

【讨论】:

    【解决方案3】:

    使用dict理解为空列表添加Nones,然后为元组列表展平:

    d = {'header_1': ['body_1', 'body_3', 'body_2'],
     'header_2': ['body_6', 'body_4', 'body_5'],
     'header_4': ['body_7', 'body_8'],
     'header_3': ['body_9'],
     'header_9': ['body_10'],
     'header_10': []}
    
    d = {k: v if bool(v) else [None] for k, v in d.items()}
    data = [(k, y) for k, v in d.items() for y in v]
    df = pd.DataFrame(data, columns= ['a','b'])
    print (df)
                a        b
    0    header_1   body_1
    1    header_1   body_3
    2    header_1   body_2
    3    header_2   body_6
    4    header_2   body_4
    5    header_2   body_5
    6    header_4   body_7
    7    header_4   body_8
    8    header_3   body_9
    9    header_9  body_10
    10  header_10     None
    

    另一种解决方案:

    data = []
    for k, v in d.items():
        if bool(v):
            for y in v:
                data.append((k, y))
        else:
            data.append((k, None))
    
    
    df = pd.DataFrame(data, columns= ['a','b'])
    print (df)
                a        b
    0    header_1   body_1
    1    header_1   body_3
    2    header_1   body_2
    3    header_2   body_6
    4    header_2   body_4
    5    header_2   body_5
    6    header_4   body_7
    7    header_4   body_8
    8    header_3   body_9
    9    header_9  body_10
    10  header_10     None
    

    【讨论】:

    • 我可以借用你的d 设置吗?
    • 非常好的/有创意的答案。您也可以使用if v 代替if bool(v)
    猜你喜欢
    • 2022-01-24
    • 2022-11-16
    • 2021-10-02
    • 1970-01-01
    • 2018-05-07
    • 2016-12-11
    • 2016-01-14
    • 2014-11-22
    相关资源
    最近更新 更多