如何用Python Pandas合并多份年度CSV数据文件?
问题描述
我有多份CSV文件,数据格式如下:
Sno,Country,2017-2018 1,AFGHANISTAN,287.1 2,ALGERIA,1286.4 3,AMERI SAMOA,9.09 4,ANGOLA,442.38 5,ARGENTINA,13881.75 6,AUSTRALIA,875706.78 7,AUSTRIA,10.45 8,AZERBAIJAN,147.87 .... so on
每份CSV文件的第3列对应不同财年的数据,我需要将2014-2024年的所有数据合并为一个CSV文件,要求同一国家的所有财年数据位于同一行。
我尝试用Pandas的concat方法合并,但结果不符合预期:同一国家的不同财年数据被拆成了多行,比如安哥拉2017-2018的值是442.38,2018-2019的实际值170.53被当成新行添加,而不是在同一行的2018-2019列显示,原来的合并方式只是把所有文件数据追加到末尾。
我的代码如下:
import pandas as pd import glob file_path = 'file_name.csv' csv_files = glob.glob(file_path) # combined_df = pd.DataFrame() combined_df = pd.read_csv("combined_data.csv") for file in csv_files: df = pd.read_csv(file) if combined_df.empty: combined_df = df else: combined_df = pd.concat([combined_df,df],ignore_index=True) combined_df = combined_df.fillna(0) combined_df.to_csv('combined_data.csv', index=False)
解决方案
问题出在concat是按行追加数据,而需要的是按Country列做横向合并,把不同财年的列拼到同一行。可以按以下两种方法实现:
方法一:逐步merge合并
通过merge方法以Country为键,依次将各文件的数据横向拼接:
import pandas as pd import glob # 获取所有CSV文件路径(根据实际路径调整,比如'./fiscal_data/*.csv') csv_files = glob.glob('*.csv') # 初始化合并后的DataFrame combined_df = None for file in csv_files: df = pd.read_csv(file) # 只保留Country和对应财年的数据列,若不需要Sno可直接丢弃 df = df[['Country', df.columns[2]]] if combined_df is None: combined_df = df else: # 按Country做外合并,保留所有国家,缺失值填充0 combined_df = pd.merge(combined_df, df, on='Country', how='outer').fillna(0) # 保存最终合并结果 combined_df.to_csv('combined_data.csv', index=False)
方法二:长表转宽表(更灵活)
先将所有文件合并成“国家-财年-数值”的长格式表,再转成“国家为行,财年为列”的宽格式表,逻辑更清晰:
import pandas as pd import glob csv_files = glob.glob('*.csv') all_data = [] for file in csv_files: df = pd.read_csv(file) # 获取当前文件对应的财年列名 fiscal_year = df.columns[2] # 整理数据格式,新增财年标识列 df = df.rename(columns={fiscal_year: 'Value'}) df['Fiscal_Year'] = fiscal_year # 保留核心列 all_data.append(df[['Country', 'Fiscal_Year', 'Value']]) # 合并所有数据为长表 long_df = pd.concat(all_data, ignore_index=True) # 转成宽表:Country作为行索引,财年作为列,数值填充对应单元格 wide_df = long_df.pivot(index='Country', columns='Fiscal_Year', values='Value').reset_index() # 填充缺失的财年数据为0 wide_df = wide_df.fillna(0) # 保存结果 wide_df.to_csv('combined_data.csv', index=False)
注意事项
- 若需要保留
Sno列,需确保所有文件中Sno与Country是一一对应的,否则合并后可能出现数据不一致;若Sno仅为各文件的行号,建议直接丢弃,以Country作为唯一标识。 - 调整
glob.glob的路径参数,匹配你的实际文件存储位置。 - 方法二更适合后续扩展,新增财年文件后无需修改核心逻辑。
内容的提问来源于stack exchange,提问作者Nilay Kamat
相关产品推荐
相关产品推荐

