python - 如何对采用列表列平均值的熊猫数据框执行 groupby 操作?
问题描述
我有一个如下所示的熊猫数据框:
df = pd.DataFrame({"A": [1, 1, 1, 2, 2],
"B": ["apple", "apple", "banana", "pineapple", "pineapple"],
"C": [[6, 5, 2], [2, 10, 2], [5, 37, 1], [4, 19, 2], [1, 5, 1]]})
现在我想对列A
和执行分组操作B
,并获得列中列表的平均值C
。多个列表的平均值被定义为按元素的平均值,因此列表第 1 位的所有第 1 个元素的平均值,列表第 2 位的所有第 2 个元素的平均值等等......
此示例所需的输出如下所示:
A B C
1 apple [4, 7.5, 2]
1 banana [5, 37, 1]
2 pineapple [2.5, 12, 1.5]
(始终保证每个组的列表具有相同的长度)
如何解决这个问题?
通常我知道如何执行 groupby 操作,无论是作为列表聚合还是作为平均值,但是在比较多个列表时我找不到如何执行此操作。如果 groupby 操作不是最有效的解决方案,我也愿意接受其他建议。
解决方案
方法一
在这里,我们从 column 中包含的列表创建一个新的数据框,C
并将这个新创建的数据框的索引设置为 columnsA
和B
。mean
现在,通过采用索引中存在的级别来聚合此框架
然后使用.values
+tolist
将平均值的视图作为 numpy 数组,将此视图转换为列表并分配给列C
s = df.set_index(['A', 'B'])
out = pd.DataFrame(list(s['C']), s.index).mean(level=[0, 1])
out.drop(out.columns.tolist(), 1).assign(C=out.values.tolist()).reset_index()
方法二
处理大数据帧时可能会变慢的幼稚方法。在这里,我们按列对数据框进行分组,A
并在 column 上使用 lambda 函数,B
然后lambda 函数从列表中创建一个 numpy 数组并取平均值apply
C
axis=0
out = df.groupby(['A', 'B'])['C'].apply(
lambda s: np.array(list(s)).mean(axis=0)).reset_index()
结果
A B C
0 1 apple [4.0, 7.5, 2.0]
1 1 banana [5.0, 37.0, 1.0]
2 2 pineapple [2.5, 12.0, 1.5]
性能分析
在具有50000行和30000个唯一组的示例数据帧上
df = pd.concat([df.assign(B=df['B'] + str(i))
for i in range(10000)], ignore_index=True)
%%timeit
s = df.set_index(['A', 'B'])
out = pd.DataFrame(list(s['C']), s.index).mean(level=[0, 1])
_ = out.drop(out.columns.tolist(), 1).assign(C=out.values.tolist()).reset_index()
# 173 ms ± 19 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
_ = df.groupby(['A', 'B'])['C'].apply(lambda s: np.array(list(s)).mean(axis=0)).reset_index()
# 2.24 s ± 68.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
推荐阅读
- c++ - 传递一个“自动”声明的 std::shared_ptr
到 std::shared_ptr & - spring-boot - 如何设置动态数据源的初始连接
- node.js - 由于引号不匹配,Jest 测试失败
- redis - 如何在redis集群中实现租户隔离以实现弹性
- vue.js - 在 Vuetify 的 VAppBar 中传播元素
- css - 当我调整浏览器窗口的大小时,如何使我的表单不会分崩离析?
- spacy - 如何仅针对 NER 优化 SpaCy 管道(使用现有模型,无需训练)
- ios - UIAlertAction 不可重用
- node.js - Sequelize Insert 记录由 Model.Create 与深度关联
- javascript - 有什么方法可以在 docker 容器中使用 puppeteer 和带有 headless:false 的 chromium 运行 NextJS?