在Pandas中高效计算分组堆叠数据框中的变量比率

花韻仙語
发布: 2025-10-16 14:52:07
原创
338人浏览过

在Pandas中高效计算分组堆叠数据框中的变量比率

本教程详细介绍了如何在pandas数据框中,针对特定分组(如g1和g2)内的变量(如tpe列中的'ts'与'td')计算比率,并将结果作为新行添加回原数据框。文章通过一个实际案例,展示了如何利用`set_index`、`unstack`和向量化操作,以高效且优雅的方式处理数据重塑、比率计算以及缺失值(nan)的填充,避免了传统`groupby().apply()`方法可能存在的性能瓶颈和复杂性。

数据框中分组比率计算的挑战与解决方案

在数据分析中,我们经常需要根据数据框中的某些列进行分组,然后计算组内特定变量之间的比率。例如,在一个包含交易类型(TPE)和数量(QC)的数据框中,我们可能需要计算每组(G1, G2)中'ts'类型数量与'td'类型数量的比率(ts/td)。此外,还需要将计算出的比率作为新行添加到原始数据框中,并且要妥善处理那些不包含完整'ts'和'td'值的组。

初始数据结构

假设我们有以下Pandas DataFrame df_in:

import pandas as pd
import numpy as np

data = {
    'G1': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'D'],
    'G2': ['S1', 'S1', 'S2', 'S2', 'S1', 'S1', 'S2', 'S2', 'S1', 'S2'],
    'TPE': ['td', 'ts', 'td', 'ts', 'td', 'ts', 'td', 'ts', 'td', 'ts'],
    'QC': [2, 4, 6, 3, 20, 40, 60, 30, 90, 7]
}
df_in = pd.DataFrame(data)

# 模拟原始数据中可能存在的缺失类型
df_in.loc[8, 'TPE'] = 'td' # C S1 只有 td
df_in.loc[9, 'TPE'] = 'ts' # D S2 只有 ts
df_in = df_in.drop(index=[8,9]).append(pd.DataFrame([['C', 'S1', 'td', 90], ['D', 'S2', 'ts', 7]], columns=df_in.columns), ignore_index=True)


print("原始数据框 df_in:")
print(df_in)
登录后复制

输出 df_in 如下:

  G1  G2 TPE  QC
0  A  S1  td   2
1  A  S1  ts   4
2  A  S2  td   6
3  A  S2  ts   3
4  B  S1  td  20
5  B  S1  ts  40
6  B  S2  td  60
7  B  S2  ts  30
8  C  S1  td  90
9  D  S2  ts   7
登录后复制

目标输出

我们的目标是生成一个包含原始数据和计算出的比率的新数据框 df_out。对于每个 (G1, G2) 组,如果同时存在 'td' 和 'ts' 类型的 QC 值,则计算 ts_QC / td_QC 作为比率,并将新行的 TPE 列标记为 'ratio'。如果缺少 'td' 或 'ts',则比率应为空(NaN)。

期望的 df_out 结构如下:

   G1  G2    TPE   QC
0   A  S1     td  2.0
1   A  S1     ts  4.0
2   A  S2     td  6.0
3   A  S2     ts  3.0
4   B  S1     td 20.0
5   B  S1     ts 40.0
6   B  S2     td 60.0
7   B  S2     ts 30.0
8   C  S1     td 90.0
9   D  S2     ts  7.0
10  A  S1  ratio  2.0
11  A  S2  ratio  0.5
12  B  S1  ratio  2.0
13  B  S2  ratio  0.5
14  C  S1  ratio  NaN
15  D  S2  ratio  NaN
登录后复制

传统 groupby().apply() 方法的局限性

一种常见的思路是使用 groupby().apply() 方法,为每个组编写一个自定义函数来计算比率。

def calculate_ratio_apply(group):
    td_row = group[group['TPE'] == 'td']
    ts_row = group[group['TPE'] == 'ts']
    if not td_row.empty and not ts_row.empty:
        ratio = ts_row['QC'].values[0] / td_row['QC'].values[0]
        return pd.DataFrame({'G1': [group['G1'].iloc[0]], 
                             'G2': [group['G2'].iloc[0]], 
                             'TPE': ['ratio'], 
                             'QC': [ratio]})
    # 如果缺少td或ts,返回一个空的DataFrame,这会导致这些组的比率行被省略
    return pd.DataFrame() 

# 这种方法会忽略没有完整td和ts值的组
# grouped = df_in.groupby(['G1', 'G2']).apply(calculate_ratio_apply).reset_index(drop=True)
# df_out_apply = pd.concat([df_in, grouped], ignore_index=True)
# print("\n使用 apply 方法(可能遗漏空比率):")
# print(df_out_apply)
登录后复制

上述 apply 方法虽然能计算比率,但如果某个组没有同时包含 'td' 和 'ts' 值,它会返回一个空的DataFrame,导致这些组的比率行被完全省略,而不是填充 NaN。对于大型数据集,apply 方法也可能因为循环迭代而导致性能问题。

KAIZAN.ai
KAIZAN.ai

使用AI来改善客户服体验,提高忠诚度

KAIZAN.ai 35
查看详情 KAIZAN.ai

优化方案:利用 unstack 和向量化操作

更高效和优雅的解决方案是利用 Pandas 的数据重塑功能,将 'TPE' 列中的 'td' 和 'ts' 值转化为独立的列,然后进行向量化计算。

# 1. 重塑数据:将 'TPE' 列中的 'td' 和 'ts' 值转换为独立的列
#    - set_index(['G1', 'G2', 'TPE']): 将这三列设为索引
#    - unstack()['QC']: 将 TPE 索引层的数据(QC值)unstack(逆透视)成列
#      结果是一个多级索引的 DataFrame,列为 TPE 的不同值(td, ts)
tmp = df_in.set_index(['G1', 'G2', 'TPE']).unstack()['QC']

print("\n中间结果 tmp (重塑后的数据):")
print(tmp)
登录后复制

中间结果 tmp 的结构如下,我们可以清晰地看到每个 (G1, G2) 组对应的 'td' 和 'ts' 值,以及缺失值(NaN):

TPE     td    ts
G1 G2           
A  S1    2.0   4.0
   S2    6.0   3.0
B  S1   20.0  40.0
   S2   60.0  30.0
C  S1   90.0   NaN
D  S2    NaN   7.0
登录后复制
# 2. 计算比率:直接对重塑后的列进行向量化除法
#    - tmp['ts'].div(tmp['td']): 计算 'ts' 列与 'td' 列的比率
#    - reset_index(name='QC'): 将多级索引重置为列,并将比率结果命名为 'QC'
#    - assign(TPE='ratio'): 添加一个新列 'TPE',其值为 'ratio'
ratio_df = tmp['ts'].div(tmp['td']).reset_index(name='QC').assign(TPE='ratio')

print("\n计算出的比率数据框 ratio_df:")
print(ratio_df)
登录后复制

计算出的比率数据框 ratio_df 如下:

  G1  G2   QC    TPE
0  A  S1  2.0  ratio
1  A  S2  0.5  ratio
2  B  S1  2.0  ratio
3  B  S2  0.5  ratio
4  C  S1  NaN  ratio
5  D  S2  NaN  ratio
登录后复制
# 3. 合并数据:将原始数据框和计算出的比率数据框进行纵向合并
df_out = pd.concat([df_in, ratio_df], ignore_index=True)

print("\n最终输出数据框 df_out:")
print(df_out)
登录后复制

最终的 df_out 完美符合我们的要求:

   G1  G2    TPE   QC
0   A  S1     td  2.0
1   A  S1     ts  4.0
2   A  S2     td  6.0
3   A  S2     ts  3.0
4   B  S1     td 20.0
5   B  S1     ts 40.0
6   B  S2     td 60.0
7   B  S2     ts 30.0
8   C  S1     td 90.0
9   D  S2     ts  7.0
10  A  S1  ratio  2.0
11  A  S2  ratio  0.5
12  B  S1  ratio  2.0
13  B  S2  ratio  0.5
14  C  S1  ratio  NaN
15  D  S2  ratio  NaN
登录后复制

完整代码示例

import pandas as pd
import numpy as np

# 原始数据框
data = {
    'G1': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B', 'C', 'D'],
    'G2': ['S1', 'S1', 'S2', 'S2', 'S1', 'S1', 'S2', 'S2', 'S1', 'S2'],
    'TPE': ['td', 'ts', 'td', 'ts', 'td', 'ts', 'td', 'ts', 'td', 'ts'],
    'QC': [2, 4, 6, 3, 20, 40, 60, 30, 90, 7]
}
df_in = pd.DataFrame(data)

# 模拟原始数据中可能存在的缺失类型,确保 C S1 只有 td,D S2 只有 ts
df_in = df_in.drop(index=[8,9]).append(pd.DataFrame([['C', 'S1', 'td', 90], ['D', 'S2', 'ts', 7]], columns=df_in.columns), ignore_index=True)

# 1. 重塑数据:将 'TPE' 列中的 'td' 和 'ts' 值转换为独立的列
#    通过 set_index 和 unstack,将数据从长格式转换为宽格式,便于计算
tmp = df_in.set_index(['G1', 'G2', 'TPE']).unstack()['QC']

# 2. 计算比率并格式化结果
#    - tmp['ts'].div(tmp['td']): 执行向量化除法,自动处理缺失值(NaN)
#    - reset_index(name='QC'): 将多级索引重置为常规列,并将比率结果列命名为 'QC'
#    - assign(TPE='ratio'): 添加一个新列 'TPE',其值为 'ratio'
ratio_df = tmp['ts'].div(tmp['td']).reset_index(name='QC').assign(TPE='ratio')

# 3. 合并数据:将原始数据框和计算出的比率数据框进行纵向合并
df_out = pd.concat([df_in, ratio_df], ignore_index=True)

print("最终输出数据框 df_out:")
print(df_out)
登录后复制

注意事项与总结

  1. 效率提升: 相比于 groupby().apply(),使用 set_index().unstack() 结合向量化操作(如 .div())在处理大型数据集时通常更高效,因为它利用了 Pandas 底层的优化 C 语言实现。
  2. 缺失值处理: unstack() 操作会自动将缺失的数据填充为 NaN。在进行除法运算时,任何包含 NaN 的运算结果仍为 NaN,这自然地满足了对“空比率”的需求。
  3. 可读性与简洁性: 这种方法代码更简洁,逻辑更清晰,避免了自定义函数中复杂的条件判断。
  4. 通用性: 这种数据重塑和向量化计算的模式适用于各种需要计算分组内变量之间比率或差值等场景。

通过本教程,您应该能够高效且优雅地在 Pandas 数据框中处理分组比率计算问题,即使面对复杂的数据结构和缺失值情况也能游刃有余。

以上就是在Pandas中高效计算分组堆叠数据框中的变量比率的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号