如何基于列标题为Pandas空DataFrame按文件添加数据行
你的代码思路没问题,但有两个小坑需要修正~
嘿,先给你吃个定心丸:你用pd.read_csv读取每个文件为索引是A/B/C的Series,再通过concat转置得到每行对应一个文件的DataFrame,这个核心逻辑是完全正确的!不过你的代码里有两个容易踩的小问题,我帮你指出来并修正:
问题1:文件路径错误
os.walk返回的files只是文件名,不是完整路径,直接用pd.read_csv(f)的话,Python会在当前脚本的目录下去找这些文件,大概率会找不到(除非你的脚本刚好和目标文件在同一个目录)。所以必须把root(当前目录路径)和name(文件名)拼接成完整路径。
问题2:外层循环冗余且会导致数据覆盖
你写了两层循环:
for root, dirs, files in os.walk(dir_M): for name in files: L = [pd.read_csv(f, ...) for f in files] df = pd.concat(...).T
这会导致:每次遍历到一个子目录,就会把该目录下的所有文件处理一遍,然后覆盖之前的df,最终df只会保留最后一个子目录下的文件数据,这显然不是你想要的。
修正后的代码
我帮你调整了代码,既解决路径问题,又避免循环冗余:
方式1:分步清晰版
import os import pandas as pd dir_M = "你的目标文件夹路径" # 替换成你的实际路径 # 第一步:收集所有目标文件的完整路径 all_file_paths = [] for root, _, files in os.walk(dir_M): # 用_忽略dirs变量,因为我们不需要遍历子目录名 for file_name in files: full_path = os.path.join(root, file_name) all_file_paths.append(full_path) # 第二步:读取每个文件为Series(索引是A/B/C,值是对应数字) series_list = [] for path in all_file_paths: # squeeze()把单列DataFrame转成Series,比[1]更稳妥 file_series = pd.read_csv(path, index_col=0, header=None, sep='\s+').squeeze() series_list.append(file_series) # 第三步:拼接所有Series并转置,得到目标DataFrame df = pd.concat(series_list, axis=1).T # 可选:重置行索引为0、1、2...(默认行索引是文件名,如果你不需要的话) df = df.reset_index(drop=True)
方式2:简洁列表推导式版
如果喜欢更紧凑的代码,可以写成:
import os import pandas as pd dir_M = "你的目标文件夹路径" all_file_paths = [os.path.join(root, name) for root, _, files in os.walk(dir_M) for name in files] df = pd.concat( [pd.read_csv(f, index_col=0, header=None, sep='\s+').squeeze() for f in all_file_paths], axis=1 ).T.reset_index(drop=True)
验证效果
用你给出的示例文件测试:
- file1内容:
A 32 B 31 C 45
- file2内容:
A 56 B 34 C 12
处理后得到的df就是:
A B C 0 32 31 45 1 56 34 12
完全符合你的预期!
另外,如果你的目标文件都直接在dir_M目录下,没有子文件夹,那可以不用os.walk,用os.listdir更简单:
all_file_paths = [os.path.join(dir_M, f) for f in os.listdir(dir_M) if os.path.isfile(os.path.join(dir_M, f))]
内容的提问来源于stack exchange,提问作者ubuntu_noob
相关产品推荐
相关产品推荐

