如何高效在DataFrame的Plassering递增分组行计算softmax函数
高效实现按分组计算Softmax的方案
核心思路是先构建分组标识,再用Pandas的分组聚合操作替代循环遍历,这比iterrows()效率高得多,完全适配5000行规模的数据集。
1. 生成分组标识列
观察数据规律:每当Plassering的值回到1时,就代表一个新分组的开始。我们可以利用这个特征生成唯一的分组ID:
import pandas as pd # 假设你的DataFrame名为df df['group_id'] = (df['Plassering'] == 1).cumsum()
这行代码会给每一段连续递增的Plassering序列分配独立的组ID,比如示例中前4行的group_id为1,接下来3行为2,以此类推。
2. 实现Softmax函数
可以写一个轻量版的Softmax函数,避免额外依赖,同时处理数值溢出问题:
import numpy as np def softmax(x): exp_x = np.exp(x - np.max(x)) # 减去最大值防止指数运算溢出 return exp_x / exp_x.sum()
如果已经安装了scipy,也可以直接用scipy.special.softmax,效果一致。
3. 分组应用Softmax
用groupby结合transform方法,直接在原DataFrame中生成计算结果列:
df['Softmax_FGrating'] = df.groupby('group_id')['Average FGrating'].transform(softmax)
transform会保留原DataFrame的索引结构,自动将每组的计算结果映射回对应行,无需手动维护列表和判断分组切换的逻辑。
完整示例代码
import pandas as pd import numpy as np # 构造示例数据 data = { 'Index': [22943, 22944, 22945, 22746, 22947, 22948, 22949], 'Plassering': [1, 2, 3, 4, 1, 2, 3], 'Average FGrating': [100.43, 93.5, 104.6, 101.3, 102.05, 107.35, 109.12] } df = pd.DataFrame(data) # 生成分组ID df['group_id'] = (df['Plassering'] == 1).cumsum() # 定义Softmax函数 def softmax(x): exp_x = np.exp(x - np.max(x)) return exp_x / exp_x.sum() # 分组计算Softmax df['Softmax_FGrating'] = df.groupby('group_id')['Average FGrating'].transform(softmax) print(df)
方案优势
- 性能碾压循环:Pandas的
groupby和transform基于向量化操作实现,底层用C优化,处理5000行数据几乎瞬间完成,比iterrows()快几十倍。 - 代码简洁易维护:无需手动处理分组切换的判断逻辑,代码逻辑清晰,出错概率低。
内容的提问来源于stack exchange,提问作者Bogdan Doicin
相关产品推荐
相关产品推荐

