
在 pandas 中用 `df.at[index, col]` 循环赋值列表时,若直接赋值同一可变对象(如列表),所有行将指向内存中同一个列表实例,导致最终全部显示最后一次修改的结果;正确做法是每次赋值时传入 `.copy()` 或新建副本。
当你在循环中反复对 df.at[index, 'test'] 赋值同一个列表对象(如 lista)时,Pandas 并不会自动深拷贝该对象——它只是将该列表的引用存入每一行。由于 lista 是一个可变对象,后续 lista.append(...) 会持续修改其内容,所有已赋值的单元格都指向这个动态变化的同一内存地址,因此最终每行显示的都是循环结束时 lista 的最终状态。
✅ 正确解法:每次赋值前创建独立副本
使用 .copy()(浅拷贝)即可满足本例需求(因内层子列表本身是新生成的,无需深拷贝):
import pandas as pd
import random
# 构造初始 DataFrame
data = {
'col1': [random.randint(0, 100) for _ in range(5)],
'col2': [random.randint(0, 100) for _ in range(5)]
}
df = pd.DataFrame(data)
df['test'] = None
lista = []
for index, row in df.iterrows():
# 生成新的随机子列表
sublist = [random.randint(0, 100) for _ in range(5)]
lista.append(sublist)
# 关键:赋值时使用 lista.copy(),确保每行保存当前状态的独立快照
df.at[index, 'test'] = lista.copy()
print(f"Index {index}: {lista}")
print("\n最终 DataFrame:")
print(df[['test']])? 输出效果(示意):
Index 0: [[82, 14, 67, 33, 91]] Index 1: [[82, 14, 67, 33, 91], [5, 77, 22, 48, 96]] Index 2: [[82, 14, 67, 33, 91], [5, 77, 22, 48, 96], [31, 88, 12, 64, 50]] ...
⚠️ 注意事项:
- ❌ 避免 df.at[index, 'test'] = lista(无 .copy());
- ✅ 若子列表中还嵌套可变对象(如字典、其他列表),且需完全隔离,请改用 copy.deepcopy(lista);
- ⚡ 性能提示:频繁使用 iterrows() + df.at 属于显式循环,在大数据量下较慢;如逻辑允许,优先考虑向量化操作或 cumsum()/expanding() 等内置累积方法;
- ? 替代思路(更 Pythonic):可用列表推导式预生成所有中间状态,再一次性赋值,避免循环中重复引用问题。
总结:Pandas 的标量赋值不自动克隆可变对象。理解「引用 vs 副本」是安全操作嵌套数据结构的关键——尤其在 df.at、df.loc 或 Series 赋值场景中,务必主动管理对象生命周期。








