如何按分组匹配实现Pandas DataFrame列与分组值的批量减法?
矩阵化实现DataFrame列按分组对应减分组值的方案
当然有高效的矩阵化实现方式,完全不需要写循环!利用pandas的广播特性和列映射能力,几行代码就能搞定,效率比循环高太多了。
思路解析
核心是先把分组字典转换成和主DataFrame列对应的映射关系,然后让分组值DataFrame按照这个映射关系重新排列列,最后直接和主DataFrame做减法——pandas会自动帮我们对齐索引和列的对应关系,完成逐列的减法操作。
完整实现代码
先把你的示例代码放出来,再加上实现逻辑:
import pandas as pd # 构建主DataFrame df = pd.DataFrame(index=pd.date_range("1/1/2018","1/10/2018"), columns= ["AAA","BBB","CCC","DDD"]) df["AAA"]=range(100,110) df["BBB"]=range(200,210) df["CCC"]=range(300,310) df["DDD"]=range(400,410) # 分组定义 Group_Dict = {"AAA":"Group1", "BBB":"Group2", "CCC":"Group1", "DDD":"Group2"} # 分组值DataFrame group_value = pd.DataFrame(index=pd.date_range("1/1/2018","1/10/2018"), columns=["Group1","Group2"]) group_value["Group1"]=range(10,29)[::2] group_value["Group2"]=range(100,600)[::50] # 方案1:利用numpy数组广播 group_map = pd.Series(Group_Dict) result = df - group_value.loc[:, group_map].values # 方案2:更直观的列对齐方式(推荐) result = df - group_value[group_map].set_axis(df.columns, axis=1)
代码解释
group_map = pd.Series(Group_Dict):把分组字典转换成Series,索引是主DataFrame的列名,值是对应的分组名称,这样就建立了列和分组的映射关系。group_value[group_map]:按照group_map的顺序从group_value中取出对应的分组值列,此时列顺序和主DataFrame完全对应(AAA对应Group1,BBB对应Group2,以此类推)。set_axis(df.columns, axis=1):把重新排列后的分组值DataFrame的列名改成主DataFrame的列名,这样做减法时pandas会直接按列名对齐,自动完成逐列的减法操作。
运行后得到的result就是你想要的每列减去对应分组值的结果,完全符合预期。
内容的提问来源于stack exchange,提问作者Research100
相关产品推荐
相关产品推荐

