You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

寻求更优Pandas方案:基于分组结果处理完整DataFrame

嘿,我懂你想摆脱低效循环的心情,这事儿用Pandas原生的向量化操作就能完美解决,而且比循环高效太多了!这里给你两种简洁的方案,都能精准匹配分组结果并完成除法计算,不匹配的行自动保留NaN:

方案一:利用索引对齐直接除法(最简洁)

这种方法的核心是利用Pandas的索引自动对齐特性,不需要额外合并操作,代码非常精简:

import pandas as pd
data = [[0.0, 2.4285714285714286, '0', 'mica02', 'd2o'], [10.0, 1.4285714285714286, '225', 'mica02', 'd2o'], [13.0, 1.0833333333333333, '225', 'mica02', 'd2o'], [954.0, 5.420454545454546, '225', 'mica02', 'air'], [937.0, 5.162534435261708, '225', 'mica02', 'air'], [75.0, 0.4966887417218543, '225', 'mica02', 'h2o'], [78.0, 0.49523809523809526, '225', 'mica02', 'h2o'], [80.0, 0.49323809523809526, '225', 'mica01', 'h2o'], ]
df0 = pd.DataFrame(data, columns=['basesubed', 'normalized', 'rot', 'm0', 'm1'])

# 1. 计算h2o分组的中位数,保留多级索引(m0, rot)
gdf = df0[df0['m1'] == 'h2o'].groupby(['m0', 'rot'])[['basesubed', 'normalized']].median()

# 2. 将原DataFrame设置为相同的多级索引,与gdf对齐后做除法,再赋值回原df
df0[['basesubed_n', 'normalized_n']] = (
    df0.set_index(['m0', 'rot'])[['basesubed', 'normalized']]
    .div(gdf, axis=0)
    .reset_index(drop=True)
)

print(df0)

运行后你会看到,第一行因为rot='0'没有对应的分组中位数,所以basesubed_n和normalized_n自动显示NaN,完全符合你的预期。

方案二:通过左连接合并后计算(更直观)

如果你更喜欢直观的合并逻辑,这种方法先把分组结果和原表合并,再进行计算,可读性更强:

import pandas as pd
data = [[0.0, 2.4285714285714286, '0', 'mica02', 'd2o'], [10.0, 1.4285714285714286, '225', 'mica02', 'd2o'], [13.0, 1.0833333333333333, '225', 'mica02', 'd2o'], [954.0, 5.420454545454546, '225', 'mica02', 'air'], [937.0, 5.162534435261708, '225', 'mica02', 'air'], [75.0, 0.4966887417218543, '225', 'mica02', 'h2o'], [78.0, 0.49523809523809526, '225', 'mica02', 'h2o'], [80.0, 0.49323809523809526, '225', 'mica01', 'h2o'], ]
df0 = pd.DataFrame(data, columns=['basesubed', 'normalized', 'rot', 'm0', 'm1'])

# 1. 计算h2o分组的中位数,重置索引以便和原表合并
gdf = df0[df0['m1'] == 'h2o'].groupby(['m0', 'rot'])[['basesubed', 'normalized']].median().reset_index()

# 2. 左连接原表和分组结果,仅匹配m0和rot列
df_merged = df0.merge(gdf, on=['m0', 'rot'], suffixes=('', '_median'), how='left')

# 3. 计算归一化后的列,不匹配的行因中位数为NaN,结果自动为NaN
df_merged['basesubed_n'] = df_merged['basesubed'] / df_merged['basesubed_median']
df_merged['normalized_n'] = df_merged['normalized'] / df_merged['normalized_median']

# 可选:删除中间的中位数列
df_merged = df_merged.drop(['basesubed_median', 'normalized_median'], axis=1)

print(df_merged)

为什么这两种方案比循环好?

这两种方法都是Pandas的向量化操作,底层用C语言实现,比Python循环快几个数量级,尤其是当你的DataFrame行数很多时,性能提升会非常明显。同时代码更简洁、易维护,也符合Pandas的最佳实践。

内容的提问来源于stack exchange,提问作者user3613114

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 09:36:36