基于列数据动态转换pandas DataFrame的实现问题求助
解决方案
你需要实现的是长表转宽表的需求,直接使用pandas内置的pivot/pivot_table方法即可实现,无需手动写循环拆分再拼接,自动适配任意数量的年份,代码更简洁不易出错。
最优实现方案
import pandas as pd # 读入原始数据 df = pd.read_csv("你的数据文件路径.csv") # 核心转换逻辑 result = df.pivot( # 固定作为行标识的公共列 index=['Country', 'state', 'sex', 'dist'], # 要扩展为列名的字段 columns='Year', # 列对应的值来源字段 values='population' # 把索引还原为普通列,匹配预期输出格式 ).reset_index() # 若存在年份缺失需要填充为0,可加以下代码 # result = result.fillna(0)
如果你的数据中存在同一个Country+state+sex+dist+Year组合有多条重复记录的情况,改用pivot_table指定聚合规则即可:
result = df.pivot_table( index=['Country', 'state', 'sex', 'dist'], columns='Year', values='population', # 可替换为'mean'/'max'等符合业务需求的聚合函数 aggfunc='sum' ).reset_index()
原循环写法的修正方案
如果你需要沿用循环的实现思路,你原来的代码主要有三个问题:
- 筛选条件里的
df.SERIAL是笔误,原数据的年份列名是Year - 列表中存入的是变量名字符串,不是实际的DataFrame对象
- 没有将
population列重命名为对应年份,也没有基于公共键做拼接,直接横向拼接会出现行不匹配的问题
修正后的代码如下:
import pandas as pd from functools import reduce df = pd.read_csv("你的数据文件路径.csv") serial = df.Year.unique() df_list = [] for year in serial: # 筛选对应年份的数据 year_df = df.loc[df['Year'] == year].copy() # 重命名population列为年份值 year_df = year_df.rename(columns={'population': str(year)}) # 删除冗余的Year列避免后续拼接冲突 year_df = year_df.drop(columns=['Year']) df_list.append(year_df) # 基于公共键做多表合并 result = reduce( lambda left, right: pd.merge( left, right, on=['Country', 'state', 'sex', 'dist'], how='outer' ), df_list )
内容的提问来源于stack exchange,提问作者jagan k
相关产品推荐
相关产品推荐

