Python pandas遍历DataFrame列表执行数据处理未生效问题
问题根因
遍历dfc列表时,循环语句里的dataset只是指向列表元素的临时变量。你写的所有DataFrame处理逻辑(条件筛选、dropna、drop、reset_index)默认都不是原地修改数据,而是返回全新的DataFrame对象,你把这些新对象赋值给临时变量dataset时,并没有修改dfc列表里原本存储的原始DataFrame,循环结束后临时变量被回收,列表里留的还是最开始读取的未处理数据,所以批量执行看起来没生效。
单独给单个DataFrame写处理逻辑时,你一般会把处理结果赋值回原变量名(比如df = df[df.dB !=0]),相当于直接把变量指向新的处理后对象,所以能正常生效。
修复方案
方案1:按索引遍历,把处理结果写回原列表
直接通过索引定位列表内的元素位置,处理完成后替换对应位置的内容即可:
dfc = [] for filename in filenames: dfc.append(pd.read_csv(filename, names=columns, header=None, delim_whitespace=True)) # 按下标遍历列表 for idx in range(len(dfc)): dataset = dfc[idx] dataset = dataset[dataset.dB != 0] dataset = dataset[dataset.B < 0] dataset = dataset.dropna() drop_cond = (dataset['dB'] + dataset['dB'].shift(1)) == 0 dataset = dataset.drop(dataset[drop_cond].index) dataset = dataset.reset_index(drop=True) dfc[idx] = dataset # 处理结果写回原列表对应位置 for dataset in dfc: display(dataset)
方案2:封装处理逻辑,用列表推导式生成处理后的新列表
把单条DataFrame的处理逻辑封装成函数,读入数据时直接批量处理,代码更简洁:
def clean_data(dataset): dataset = dataset[dataset.dB != 0] dataset = dataset[dataset.B < 0] dataset = dataset.dropna() drop_cond = (dataset['dB'] + dataset['dB'].shift(1)) == 0 dataset = dataset.drop(dataset[drop_cond].index) return dataset.reset_index(drop=True) # 读取+处理一步完成 dfc = [ clean_data(pd.read_csv(fname, names=columns, header=None, delim_whitespace=True)) for fname in filenames ] for dataset in dfc: display(dataset)
排查要点
- 记清pandas操作的默认行为:除了明确指定
inplace=True的操作,绝大多数筛选、变形、删除操作都会返回新DataFrame,不会修改原始对象 - 调试时可以在循环内分别打印临时变量
dataset的长度、和dfc[i]的内存地址,就能快速发现临时变量和原列表元素已经不是同一个对象 - 批量处理容器内元素时,不要仅给循环临时变量赋值,要么通过索引/切片修改原容器内容,要么直接生成新容器存储处理结果,避免出现修改不生效的问题
内容的提问来源于stack exchange,提问作者Dr.Viper
相关产品推荐
相关产品推荐

