如何在DataFrame中使各公司数据乘以对应Total General值且保留该值不变
问题解决:透视表数值按年份乘以对应Total General值
问题描述
通过代码生成了以Company为行索引、Year(2023/2024)为列索引的透视表,需求是:
- Amazon、Chedraui等公司的各年份数值,乘以对应年份的
Total General数值 Total General行的数值保持不变
尝试实现时触发KeyError: "None of ['Year'] are in the columns",原因是透视表的Year是列索引,而非普通DataFrame列,原代码错误地将其当作普通列处理。
错误代码分析
原代码中df_3 = pd.DataFrame(df_2).set_index('Year')这一行存在问题:df_2的Year是列名(即列索引),不是DataFrame的普通列,因此无法通过set_index('Year')找到对应列,导致KeyError。
正确解决方案
核心思路
- 提取
Total General行的数值,作为各年份的乘数 - 对非
Total General的公司行,让每一列(年份)的数值乘以对应年份的乘数 - 将处理后的公司行与原
Total General行合并,得到最终结果
修正后的完整代码
import pandas as pd import matplotlib.pyplot as plt from rich import print def plot_som_charts(catcp_filter,mesesin): df = pd.read_csv('data_graf_som.csv') # 数据过滤 df['Date'] = pd.to_datetime(df['Month.1']) df = df[(df['Year'] == 2023) & (df['Date'].dt.month <= mesesin) | (df['Year'] == 2024) & (df['Date'].dt.month <= mesesin)] df = df[df['CATCP'] == catcp_filter] # 计算各公司YTD数据 grouped = df.groupby(['Year', 'Company']).agg({ ' CPUSD': 'sum', ' SalesCD': 'sum' }).reset_index() # 计算年度Total General total_general = grouped.groupby('Year').agg({ ' CPUSD': 'sum', ' SalesCD': 'sum' }).reset_index() total_general['Company'] = 'Total General' # 合并数据并计算SOM result = pd.concat([grouped, total_general], ignore_index=True) result = result.sort_values(by=['Year', 'Company']).reset_index(drop=True) result['SOM'] = result[' CPUSD'] / result[' SalesCD'] # 生成透视表 pivot_df_year = result.pivot(index='Company', columns='Year', values='SOM') return pivot_df_year # 生成原始透视表 df_2 = plot_som_charts('TP',6) # ==================== 核心处理部分 ==================== # 提取Total General作为各年份的乘数 total_gen_values = df_2.loc['Total General'] # 筛选非Total General的公司行,进行乘法运算 other_companies = df_2.drop('Total General') * total_gen_values # 合并处理后的公司行与原Total General行 df_3 = pd.concat([other_companies, df_2.loc[['Total General']]]) # 保持原行顺序(可选,根据需求调整) df_3 = df_3.reindex(df_2.index) print(df_3)
关键代码解释
total_gen_values = df_2.loc['Total General']:直接提取Total General行的所有年份数值,得到一个Series,索引为年份df_2.drop('Total General') * total_gen_values:利用Pandas的广播机制,非Total General行的每一列(年份)都会自动对应乘以total_gen_values中相同年份的数值pd.concat([other_companies, df_2.loc[['Total General']]]):将处理后的公司数据与原Total General行合并,保证Total General数值不变df_3.reindex(df_2.index):可选步骤,用于保持原始透视表的行顺序(比如让Total General仍在最后)
内容的提问来源于stack exchange,提问作者BP_Nayib Akele
相关产品推荐
相关产品推荐

