如何创建指定列对列表并通过For循环处理Pandas DataFrame计算
解决Pandas多列指定位置计算的循环优化
问题背景
我有一个包含多级索引列的Pandas DataFrame,需要对基于位置指定的特定列对执行差值和百分比变化计算(比如第8列和第1列、第8列和第7列)。目前通过手动重复代码实现,希望改成循环批量处理,但不知道如何创建正确的列对列表。
原手动实现代码:
import numpy as np import pandas as pd data = [[99,3,12,4,63,55,67,32,15,102,87,34,82,102,99,30,99,1]] cols_m = pd.MultiIndex.from_product([['1. FY21','2. FY22','3. FY23','4. FY24','5. FY25','6. FY26','7. FY27','8. FY28','9. FY29'],['Values','Sites']]) df = pd.DataFrame(data, columns = cols_m) cols = df.columns.get_level_values(0).unique() first_col = df.xs(cols[1], level=0, axis=1) second_col = df.xs(cols[8], level=0, axis=1) d = second_col - first_col e = (second_col/first_col - 1) * 100 d = pd.concat({f"{cols[8]}-{cols[1]}": d}, axis=1) e = pd.concat({f"{cols[8]}-{cols[1]} %Change": e}, axis=1) df = pd.concat([df, d, e], axis=1) del first_col, second_col, d, e first_col = df.xs(cols[7], level=0, axis=1) second_col = df.xs(cols[8], level=0, axis=1) d = second_col - first_col e = (second_col/first_col - 1) * 100 d = pd.concat({f"{cols[8]}-{cols[7]}": d}, axis=1) e = pd.concat({f"{cols[8]}-{cols[7]} %Change": e}, axis=1) df = pd.concat([df, d, e], axis=1) # 后续还有更多重复代码...
解决方案
1. 构建列对列表
创建元组列表来定义需要计算的列索引对,每个元组的格式为(被减数/除数的列索引, 减数/被除数的列索引),对应你需求中的cols[i]和cols[j]。比如你需要的两组计算,就写成:
column_pairs = [(1, 8), (7, 8)] # 可继续添加更多列对,如(0,8), (2,8)等
2. 修改后的完整循环代码
import numpy as np import pandas as pd data = [[99,3,12,4,63,55,67,32,15,102,87,34,82,102,99,30,99,1]] cols_m = pd.MultiIndex.from_product([['1. FY21','2. FY22','3. FY23','4. FY24','5. FY25','6. FY26','7. FY27','8. FY28','9. FY29'],['Values','Sites']]) df = pd.DataFrame(data, columns = cols_m) cols = df.columns.get_level_values(0).unique() # 定义需要计算的列索引对 column_pairs = [(1, 8), (7, 8)] # 循环处理每一组列对 for i, j in column_pairs: first_col = df.xs(cols[i], level=0, axis=1) second_col = df.xs(cols[j], level=0, axis=1) # 计算差值和百分比变化 diff = second_col - first_col pct_change = (second_col / first_col - 1) * 100 # 为结果添加多级索引列名 diff = pd.concat({f"{cols[j]}-{cols[i]}": diff}, axis=1) pct_change = pd.concat({f"{cols[j]}-{cols[i]} %Change": pct_change}, axis=1) # 将结果拼接到原DataFrame df = pd.concat([df, diff, pct_change], axis=1)
关键说明
- 用元组列表而非集合:集合是无序结构,循环时列对顺序不可控,而列表能保证按你定义的顺序执行计算
- 循环复用计算逻辑:避免了手动重复代码,后续新增列对只需在
column_pairs中添加元组即可 - 保持原计算逻辑:差值和百分比变化的计算方式与手动代码完全一致,输出结果完全匹配
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

