for循环含if语句的作用域问题:pandas.append循环中无效
问题根源:你忽略了
DataFrame.append()的「不可变性」 哈哈,这个坑我刚用pandas的时候也踩过!你遇到的核心问题,是没搞清楚pandas.DataFrame.append()的本质——它不会修改原DataFrame对象,每次调用都会返回一个全新的DataFrame。如果循环里只调用append()但不把返回的新对象重新赋值给结果变量,那你的结果变量永远停留在第一次修改后的状态,后面的所有append操作等于白做。
举个和你场景对应的例子,你大概率写了类似这样的代码:
import pandas as pd result_df = pd.DataFrame() for i in range(10): if i == 0: temp_df = pd.DataFrame({'value': [i]}) # 这里你赋值了,result_df变成包含i=0的新DataFrame result_df = result_df.append(temp_df, ignore_index=True) else: temp_df = pd.DataFrame({'value': [i]}) # 这里只调用append但没赋值!原result_df根本没变 result_df.append(temp_df, ignore_index=True) print(result_df) # 自然只显示i=0的那一行
两种解决办法,推荐第二种(高效又稳妥)
办法1:每次append都强制赋值
把循环里的append操作都改成「赋值回结果变量」,确保每次都拿到最新的合并后DataFrame:
result_df = pd.DataFrame() for i in range(10): temp_df = pd.DataFrame({'value': [i]}) # 关键:必须把append返回的新对象重新赋值给result_df result_df = result_df.append(temp_df, ignore_index=True)
不过要注意:append()在pandas 2.0及以上版本已经被官方弃用了,未来可能会移除,所以更推荐下面的方法。
办法2:用列表收集所有小DataFrame,最后一次性合并
这是pandas官方推荐的高效写法,避免循环中反复创建新对象带来的性能损耗:
# 先初始化一个空列表,用来装每个循环生成的小DataFrame df_collection = [] for i in range(10): if i == 0: temp_df = pd.DataFrame({'value': [i]}) else: temp_df = pd.DataFrame({'value': [i]}) # 把小DataFrame加入列表,这一步只是存引用,几乎没性能开销 df_collection.append(temp_df) # 最后用concat一次性合并所有数据,ignore_index=True重置索引 result_df = pd.concat(df_collection, ignore_index=True)
适配你的业务场景
结合你提到的「每行产品数据调用dmd_flow生成12个月序列」的需求,直接套用第二种方法就行:
import pandas as pd # 假设input_df是你的产品数据输入DataFrame df_collection = [] for idx, product_row in input_df.iterrows(): # 用当前行数据调用dmd_flow生成12个月序列,转成DataFrame monthly_flow_df = pd.DataFrame(dmd_flow(product_row)) # 把这个产品的月度数据加入列表 df_collection.append(monthly_flow_df) # 合并所有产品的月度数据,得到最终结果 final_result = pd.concat(df_collection, ignore_index=True)
这种写法不仅解决了你「只保留第一个分支数据」的问题,还能大幅提升处理大数据量时的运行效率,比循环append快好几倍。
内容的提问来源于stack exchange,提问作者ivan7707
相关产品推荐
相关产品推荐

