我有一个包含两列列表的数据框架:
>>> import pandas as pd
>>> df = pd.DataFrame({'A': ['x1','x2','x3', 'x4'], 'B':[['v1','v2'],['v3','v4'],['v6'],['v7','v8']], 'C':[['c1','c2'],['c3','c4'],['c5','c6'],['c7']]})
>>> df
A B C
0 x1 [v1, v2] [c1, c2]
1 x2 [v3, v4] [c3, c4]
2 x3 [v6] [c5, c6]
3 x4 [v7, v8] [c7]
我想要展开B和C列,所以输出看起来像这样:
>>> df_exploded
A B C
0 x1 v1 c1
1 x1 v2 c2
2 x2 v3 c3
3 x2 v4 c4
4 x3 v6 c5
5 x3 v6 c6
6 x4 v7 c7
7 x4 v8 c7
我目前的解决方案是首先分离行,其中B列和C列中的元素具有相同的长度并运行df.explode(["B", "C"])
,对于其余行,运行df.explode("B")
,然后运行df.explode("C")
我想知道是否有更好的解决办法。
使用itertools.zip_longest
import itertools
df1 = (df.apply(lambda x: list(itertools.zip_longest(x['B'], x['C'])), axis=1)
.explode()
.apply(lambda x: pd.Series(x, index=['B', 'C']))
.groupby(level=0).ffill())
df1
B C
0 v1 c1
0 v2 c2
1 v3 c3
1 v4 c4
2 v6 c5
2 v6 c6
3 v7 c7
3 v8 c7
通过使用df1
df[['A']].join(df1)
输出:
A B C
0 x1 v1 c1
0 x1 v2 c2
1 x2 v3 c3
1 x2 v4 c4
2 x3 v6 c5
2 x3 v6 c6
3 x4 v7 c7
3 x4 v8 c7
如果你愿意,你可以使用reset_index
索引
是的,有一个更好的解决方案。您可以同时在两列上使用explode
方法,而不是将B列和C列中的列表具有相同长度的行分开,它将自动处理列表具有不同长度的行。你可以这样做:
df_exploded = df.explode(["B", "C"])
这将给你期望的输出:
A B C
0 x1 v1 c1
1 x1 v2 c2
2 x2 v3 c3
3 x2 v4 c4
4 x3 v6 c5
5 x3 v6 c6
6 x4 v7 c7
7 x4 v8 c7