用for循环按ticker与ownership列拆分Pandas DataFrame的问题排查
为什么原代码拆出来的全是空表
你的循环逻辑踩了Python可变对象赋值的经典坑:
循环里的df只是每次迭代的临时局部变量,你把筛选出来的新表赋值给这个临时变量,只会改变它自己的内存指向,完全不会修改df_list里存的、最开始初始化的三个空DataFrame。等循环跑完,临时变量直接被销毁,外面定义的df_vusa、df_iaex、df_vwrl还是最开始创建的空表,自然没有数据。
可以用最简单的逻辑验证这个机制:
my_list = [0, 0, 0] for item in my_list: item = 100 # 给临时变量item赋值,完全不会改动原列表内容 print(my_list) # 运行后输出仍是 [0, 0, 0]
正确实现方式
写法1:直观直写(适合固定少量拆分场景)
不需要提前初始化空表、不需要套循环,直接按条件给变量赋值,逻辑最清晰:
print('splitting dataframe per ticker and ownership ... ') # 合并两个筛选条件一次过滤,加copy避免Pandas链式赋值警告 df_vusa = df_portfolio.loc[ (df_portfolio['ticker'] == 'VUSA.AS') & (df_portfolio['ownership'] == True) ].copy() df_iaex = df_portfolio.loc[ (df_portfolio['ticker'] == 'IAEX.AS') & (df_portfolio['ownership'] == True) ].copy() df_vwrl = df_portfolio.loc[ (df_portfolio['ticker'] == 'VWRL.AS') & (df_portfolio['ownership'] == True) ].copy()
写法2:循环批量处理(适合拆分规则多、列表长的场景)
如果需要保留循环逻辑,要把筛选结果主动存入列表,循环结束后再拆给对应命名变量,不要依赖循环内临时变量的赋值反向修改外部对象:
print('splitting dataframe per ticker and ownership ... ') target_tickers = ['VUSA.AS', 'IAEX.AS', 'VWRL.AS'] split_result = [] for ticker in target_tickers: # 布尔列的True判断可以直接简化为列本身,和ownership==True完全等价 sub_df = df_portfolio.loc[ (df_portfolio['ticker'] == ticker) & (df_portfolio['ownership']) ].copy() split_result.append(sub_df) # 将列表结果按顺序赋值给对应命名的子数据框 df_vusa, df_iaex, df_vwrl = split_result
关键注意点
- 筛选后加
.copy()是为了规避Pandas的SettingWithCopyWarning,避免后续修改子表时意外改动原始的df_portfolio数据 - 合并筛选条件时用
&连接,每个条件要单独加括号,避免运算符优先级导致的筛选逻辑错误 - 布尔型列的
列名 == True写法可以直接简化为列名,运行结果完全一致,代码更简洁
内容的提问来源于stack exchange,提问作者YellowSkin
相关产品推荐
相关产品推荐

