将嵌套的pandas dataframe展开为列,并为每行重复父行
我有一个 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
个值,因此它的a
和b
的值会重复出现 3 次,每次对应c
中的一行 - 如果这样更简单,我可以把这一行:
df['c'] = [df_c1.T, df_c2.T]
改成不转置的形式:df['c'] = [df_c1, df_c2]
,但源数据必须是显示的 JSON 格式。
我现在的解决办法(差不多)是遍历原始的 'c'
列中的每个元素,然后和它的父行做连接,同时切片出我想保留的列。我把这个数据框添加到一个列表中,最后对所有的数据框进行 pd.concat
操作。
这个方法慢得让人不爽,但能用。不过我希望能有更快更优雅的解决方案。
1 个回答
2
我不太明白你为什么要创建一个每个元素都是数据框的列。不过你可以用 pandas.concat
和 pandas.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