
在 pandas 中直接对含列表的列进行原地修改(如 list.insert())会导致原始 DataFrame 被意外更改,因为列表对象是可变引用类型;正确做法是创建深拷贝或使用向量化操作避免副作用。
在 pandas 中直接对含列表的列进行原地修改(如 list.insert())会导致原始 dataframe 被意外更改,因为列表对象是可变引用类型;正确做法是创建深拷贝或使用向量化操作避免副作用。
当你在循环中执行 col_2_list = df["col_2"][i] 时,获取的并非列表副本,而是对原始列表对象的引用。因此后续调用 col_2_list.insert(0, col_1_value) 实际上是在原 DataFrame 的底层列表上操作——这正是原始数据被修改的根本原因。
✅ 推荐解决方案:避免引用,使用向量化 + 深拷贝
方案一:显式深拷贝(最直观、易理解)
import pandas as pd
import copy
dict_for_df = {
"col_1": ["A", "B", "C"],
"col_2": [["D", "E"], ["F", "H"], ["I", "J"]],
}
df = pd.DataFrame(dict_for_df)
# 创建新列 col_2_modified,不改动原 df['col_2']
df["col_2_modified"] = df.apply(
lambda row: [row["col_1"]] + row["col_2"], # 安全拼接,不修改原列表
axis=1
)
# 此时原 df['col_2'] 保持不变,且无副作用
print(df[["col_1", "col_2", "col_2_modified"]])
输出:
col_1 col_2 col_2_modified 0 A [D, E] [A, D, E] 1 B [F, H] [B, F, H] 2 C [I, J] [C, I, J]
⚠️ 注意:切勿使用
df["col_2"].copy()或浅拷贝——它只复制 Series,内部列表仍为引用;必须对每个列表单独深拷贝(如copy.deepcopy(row["col_2"])),但通常无需如此复杂。
方案二:纯向量化(高效、无循环、推荐用于大数据)
# 利用 map + 列表拼接,完全避免引用问题 df["col_2_new"] = df["col_1"].map(lambda x: [x]) + df["col_2"]
该写法利用 pandas 对 list 类型的向量化拼接(+ 操作符重载),每个 [x] 是新建列表,df["col_2"] 中的原始列表未被修改,语义清晰且性能优异。
❌ 错误示范(应避免)
# 危险!会污染原始 df
for i in range(len(df)):
df["col_2"][i].insert(0, df["col_1"][i]) # 修改了原列表引用
# 同样危险:赋值后仍共享引用
temp_list = df["col_2"][0]
temp_list.append("X") # 原 df["col_2"][0] 也被改写
总结
- pandas 中含
list的列存储的是对象引用,非值拷贝; - 所有就地修改(
append,insert,extend等)均会影响原始 DataFrame; - 安全实践:使用
+拼接、map构造新列表,或apply返回新对象; - 如需保留原始列不变,始终将结果赋给新列(如
"col_2_new"),而非覆盖原列。
遵循以上原则,即可在保证数据隔离的前提下,高效完成列表级字段的转换与扩展。











