For循环处理多Pandas DataFrame时concat操作未生效问题
问题:循环批量处理DataFrame时无法更新原始对象
尝试用for循环批量处理多个DataFrame(示例为2个,实际数量更多),循环中删除列的操作看似正常,但concat操作未生效,无法更新dfs列表中引用的原始DataFrame。循环内打印能得到预期结果,但外部打印原始DataFrame A时,并未更新为预期的Anew。
简化示例代码:
import numpy as np import pandas as pd data = [['Alex',10],['Bob',12],['Clarke',13]] data2 = ['m','m','x'] A = pd.DataFrame(data, columns=['Name','Age']) B = pd.DataFrame(data, columns=['Name','Age']) C = pd.DataFrame(data2, columns=['Gender']) #expected result for A: Anew=pd.DataFrame([['Alex','m'],['Bob','m'],['Clarke','x']], columns=['Name', 'Gender']) dfs = [A,B] for k, v in enumerate(dfs): # The following line works as expected on A an B respectively, inplace is required to actually modify A,B as defined above dfs[k]=v.drop('Age',axis=1, inplace=True) # The following line doesn't do anything, I was expecting Anew (see above) dfs[k] = pd.concat([v, C], axis=1) # The following line prints the expected result within the loop print(dfs[k]) # This just shows A, not Anew: To me tha tmeans A was never updated with dfs[k] as I thought it would. print(A)
核心问题分析
inplace=True的副作用:v.drop('Age', axis=1, inplace=True)会直接修改原始DataFramev(即A和B),但该方法返回值是None。你将None赋值给dfs[k]后,后续pd.concat只是把列表对应位置替换成了新DataFrame,但这个新对象和原始的A、B没有引用关系。- Python引用赋值逻辑:列表
dfs初始存储的是A、B的引用,但执行dfs[k] = 新对象时,仅修改了列表内的引用指向,并未改变原始的A、B本身。循环内打印的是新生成的对象,外部的A还是最初的那个实例。
解决方案
方案1:直接更新原始DataFrame变量
通过索引判断直接修改原始变量,适合数量较少的场景:
import numpy as np import pandas as pd data = [['Alex',10],['Bob',12],['Clarke',13]] data2 = ['m','m','x'] A = pd.DataFrame(data, columns=['Name','Age']) B = pd.DataFrame(data, columns=['Name','Age']) C = pd.DataFrame(data2, columns=['Gender']) dfs = [A,B] for k, v in enumerate(dfs): # 先删除列(不用inplace,返回新对象),再拼接C updated_df = v.drop('Age', axis=1) updated_df = pd.concat([updated_df, C], axis=1) # 直接更新原始变量 if k == 0: A = updated_df elif k == 1: B = updated_df dfs[k] = updated_df print(A) # 输出预期的Anew
方案2:用字典存储,批量更新更灵活
如果DataFrame数量多,用字典映射名称和对象,避免索引判断:
import numpy as np import pandas as pd data = [['Alex',10],['Bob',12],['Clarke',13]] data2 = ['m','m','x'] df_dict = { 'A': pd.DataFrame(data, columns=['Name','Age']), 'B': pd.DataFrame(data, columns=['Name','Age']) } C = pd.DataFrame(data2, columns=['Gender']) for name in df_dict: df = df_dict[name] updated_df = df.drop('Age', axis=1) df_dict[name] = pd.concat([updated_df, C], axis=1) # 通过键名获取更新后的DataFrame print(df_dict['A'])
方案3:生成新列表,不修改原始对象
如果不需要保留原始A、B,直接生成处理后的新列表即可:
import numpy as np import pandas as pd data = [['Alex',10],['Bob',12],['Clarke',13]] data2 = ['m','m','x'] A = pd.DataFrame(data, columns=['Name','Age']) B = pd.DataFrame(data, columns=['Name','Age']) C = pd.DataFrame(data2, columns=['Gender']) dfs = [A,B] processed_dfs = [] for v in dfs: updated_df = v.drop('Age', axis=1) updated_df = pd.concat([updated_df, C], axis=1) processed_dfs.append(updated_df) # 处理后的结果存储在processed_dfs中 print(processed_dfs[0])
内容的提问来源于stack exchange,提问作者Cattoaster
相关产品推荐
相关产品推荐

