将嵌套的pandas dataframe展开为列,并为每行重复父行

1 投票
1 回答
2613 浏览
提问于 2025-04-18 02:28

我有一个 pandas 的数据框,基本上长得像这样:

import json
import pandas as pd

df = pd.DataFrame([
    {'a': 1,  'b': 2,  'extra': 0},
    {'a': 10, 'b': 20, 'extra': 0}
])

df_c1 = pd.io.json.read_json(json.dumps({'row1': {'c1': -1, 'c2': -2}}))

df_c2 = pd.io.json.read_json(json.dumps({
    'row1': {'c1': -10,   'c2': -20},
    'row2': {'c1': -100,  'c2': -200},
    'row3': {'c1': -1000, 'c2': -2000}
}))

df['c'] = [df_c1.T, df_c2.T]

我想把它变成这样:

比如:

goal = pd.concat([
    pd.DataFrame({'row1': {'a': 1,  'b': 2,  'c1': -1,    'c2': -2}}).T,
    pd.DataFrame({'row1': {'a': 10, 'b': 20, 'c1': -10,   'c2': -20}}).T,
    pd.DataFrame({'row2': {'a': 10, 'b': 20, 'c1': -100,  'c2': -200}}).T,
    pd.DataFrame({'row3': {'a': 10, 'b': 20, 'c1': -1000, 'c2': -2000}}).T
])

In [1]: goal
Out[1]:
       a   b    c1    c2
row1   1   2    -1    -2
row1  10  20   -10   -20
row2  10  20  -100  -200
row3  10  20 -1000 -2000

[4 rows x 4 columns]

有几点需要注意:

  • 索引要和 c 列对应行的索引一致
  • 我只想保留 ['a', 'b']'extra' 列要去掉
  • 主数据框 df 的第二行在 df['c'] 中有 3 个值,因此它的 ab 的值会重复出现 3 次,每次对应 c 中的一行
  • 如果这样更简单,我可以把这一行:df['c'] = [df_c1.T, df_c2.T] 改成不转置的形式:df['c'] = [df_c1, df_c2],但源数据必须是显示的 JSON 格式。

我现在的解决办法(差不多)是遍历原始的 'c' 列中的每个元素,然后和它的父行做连接,同时切片出我想保留的列。我把这个数据框添加到一个列表中,最后对所有的数据框进行 pd.concat 操作。

这个方法慢得让人不爽,但能用。不过我希望能有更快更优雅的解决方案。

1 个回答

2

我不太明白你为什么要创建一个每个元素都是数据框的列。不过你可以用 pandas.concatpandas.merge 来完成这个任务:

# your setup code here
df2 = pd.concat(df['c'].tolist(), keys=df.index)
df3 = pd.merge(df[["a", "b"]], df2, left_index=True, right_on=df2.index.get_level_values(0))
df4 = df3.drop("key_0", axis=1).reset_index(level=0, drop=True)
print df4

这是输出结果:

       a   b    c1    c2
row1   1   2    -1    -2
row1  10  20   -10   -20
row2  10  20  -100  -200
row3  10  20 -1000 -2000

撰写回答