合并DataFrame后使用loc赋值元组到单元格失败的原因及解决方法
你遇到的这个问题其实是Pandas中loc赋值逻辑的一个常见“小陷阱”,咱们一步步拆解原因和解决办法:
为什么会触发这个错误?
当你执行df.loc[1, '1'] = (1,2)时,Pandas的默认逻辑会把元组(或列表这类可迭代对象)当成要分配给多列的一组值,而非单个单元格的完整内容。
尤其是在你合并了Supplies列之后,DataFrame同时包含两种不同类型的列:存储元组的object类型列,和存储整数的数值列。这时候Pandas的赋值逻辑会误判你是要给多个列赋值,于是会检查可迭代对象的长度是否与目标列数匹配——你的元组长度为2,但只指定了1列,自然就抛出了ValueError: Must have equal len keys and value when setting with an iterable错误。
而df.at是Pandas专门为单个单元格的标量赋值设计的API,它不会尝试“展开”可迭代对象,而是直接将元组作为完整的标量值存入目标单元格,所以不会出现这个问题。
可行的解决办法
方法1:使用df.at直接赋值(最推荐)
这是你已经发现的方案,简单直接,完全适配单个单元格的可迭代对象赋值需求:
df.at[1, '1'] = (1,2)
方法2:用loc时将列名包装为列表
如果坚持要使用loc,可以把目标列名放在列表里,明确告诉Pandas你是要给单列的指定行赋值,而非展开可迭代对象分配给多列:
df.loc[1, ['1']] = [(1,2)]
这里把列名'1'改为['1'],同时将元组放在列表中,Pandas就会正确识别这是要给该单元格存入元组值。
方法3:明确指定列的object类型(可选)
如果列的类型存在歧义,也可以先将目标列强制设置为object类型,确保Pandas将元组视为单个元素处理:
# 把存储元组的列都转为object类型 for col in ['1', '2', '3', '4']: df[col] = df[col].astype(object) # 之后即可正常用loc赋值 df.loc[1, '1'] = (1,2)
这个方法不如前两种直接,一般仅在列类型混乱时使用。
验证效果
以方法2为例,执行赋值后打印DataFrame,会得到符合预期的结果:
1 2 3 4 Supplies 0 (10, 0) (2, 0) (20, 0) (11, 0) 1 1 (1,2) (7, 0) (9, 0) (20, 0) 2 2 (2, 0) (14, 0) (16, 0) (18, 0) 3
备注:内容来源于stack exchange,提问作者Alex Anushat

