如何在 Python Pandas 中扩展存储为单个值的可迭代对象? (又名反向分组)[重复]
Posted
技术标签:
【中文标题】如何在 Python Pandas 中扩展存储为单个值的可迭代对象? (又名反向分组)[重复]【英文标题】:How to expand an iterable stored as a single value in Python Pandas? (a.k.a. reverse groupby) [duplicate] 【发布时间】:2021-10-24 00:22:57 【问题描述】:我有以下数据框:
Index Letter Numbers
1 A [1, 11]
2 B [2, 22]
3 C [3, 33]
我想“扩展”数字列表,这样每个数字都有自己的行,如下所示:
Index Letter Numbers
1 A 1
2 A 11
3 B 2
4 B 22
5 C 3
6 C 33
我尝试使用以下代码来实现这一点:
import pandas as pd
df = pd.DataFrame(
'Letter': ['A', 'B', 'C'],
'Numbers': [[1, 11], [2, 22], [3, 33]]
)
for i, row in df.iterrows():
for num in row['Numbers']:
new_row = row.copy()
new_row['Numbers'] = num
df = df.append(new_row, ignore_index=True)
df = df.loc[df.apply(lambda x: type(x['Numbers']) != list, axis=1)]
它适用于示例,但在更大的 DataFrame(例如几十万行)中需要很多时间。有没有更好、更优化的方法来做到这一点?我尝试使用 apply 方法,但由于某种原因它清除了我的 DataFrame...
【问题讨论】:
使用explode
:df.explode('Numbers')
explode
是最用户友好的选项。但它可能会很慢,因为这样的操作不能很好地扩展。如果性能是一个真正的要求,有一些方法可以使用numpy
来重构 DataFrame。如果您知道所有列表的大小都相同,则可能非常简单,否则您需要非常小心,并且可能会变得有点混乱
【参考方案1】:
使用explode
垂直扩展值:
>>> df.explode('Numbers', ignore_index=True)
Letter Numbers
0 A 1
1 A 11
2 B 2
3 B 22
4 C 3
5 C 33
使用apply(pd.Series
) 水平扩展值:
>>> df.join(df['Numbers'].apply(pd.Series)
.add_prefix('Numbers_')) \
.drop(columns='Numbers')
Letter Numbers_0 Numbers_1
0 A 1 11
1 B 2 22
2 C 3 33
【讨论】:
【参考方案2】:正如 cmets 中已经提到的,如果您没有大量数据要解析,那么使用 df.explode()
真的很容易
>>> df
Letter Numbers
0 A [1, 11]
1 B [2, 22]
2 C [3, 33]
解决方案 1
>>> df = df.explode('Numbers')
>>> df
Letter Numbers
0 A 1
0 A 11
1 B 2
1 B 22
2 C 3
2 C 33
解决方案 2:
np.repeat
会更快...
>>> lens = [len(item) for item in df['Numbers']]
>>> pd.DataFrame( "Letter" : np.repeat(df['Letter'].values,lens), "Numbers" : np.hstack(df['Numbers']))
Letter Numbers
0 A 1
1 A 11
2 B 2
3 B 22
4 C 3
5 C 33
其他解决方案..
df.explode('Numbers', ignore_index=True)
# df.explode('Numbers').reset_index(drop=True)
Letter Numbers
0 A 1
1 A 11
2 B 2
3 B 22
4 C 3
5 C 33
使用 apply + pd.Series
>>> df.set_index('Letter').Numbers.apply(pd.Series).stack().reset_index(level=0).rename(columns=0:'Numbers')
Letter Numbers
0 A 1
1 A 11
0 B 2
1 B 22
0 C 3
1 C 33
注意:
同时,我已经看到了同样here another Solutions 的有趣答案
编码愉快!
【讨论】:
以上是关于如何在 Python Pandas 中扩展存储为单个值的可迭代对象? (又名反向分组)[重复]的主要内容,如果未能解决你的问题,请参考以下文章
Pandas:如何将 cProfile 输出存储在 pandas DataFrame 中?