如何正确赋值嵌套DataFrame?三种赋值异常解析
问题解释与解决方案
三种赋值方式的行为原因
1. frame.loc[0]['B'] = pandas.DataFrame()
这是链式索引操作:先通过loc[0]取出一行(返回Series),再通过['B']取该行的B列元素。pandas无法保证loc[0]返回的是原DataFrame的视图还是副本,因此赋值操作可能只修改了副本,原DataFrame没有变化,同时触发SettingWithCopyWarning警告,提示这种赋值行为不可靠。
2. frame.loc[0, 'B'] = pandas.DataFrame()
pandas默认期望单元格存储标量或可被解析为标量的数据。当你尝试将二维结构的DataFrame赋值给单个单元格时,pandas无法将其作为单一对象存储,会自动尝试“扁平化”这个结构,最终因无法解析而将单元格值设为NaN。而如果赋值的是非pandas对象(如普通列表、字典),这些属于可直接存储的Python对象,pandas会将它们保留在object类型的列中,因此能正常赋值。
3. frame['B'][0] = pandas.DataFrame()
这同样是链式索引:先取B列(返回Series),再取索引0的元素。虽然也触发SettingWithCopyWarning,但此时修改的是原DataFrame中B列Series的元素,因此赋值成功。不过链式索引的行为本身是不确定的(可能返回视图或副本),所以警告依然存在,不推荐依赖这种方式。
无警告的正确赋值方法
要将DataFrame作为对象存储在单元格中,需确保目标列的 dtype 为object,并使用单元素定位赋值(避免链式索引):
import pandas data = {'A': [1]} frame = pandas.DataFrame(data) # 初始化B列为object类型的列,避免pandas自动推断为其他类型 frame['B'] = [None] # 使用at进行精准单元素赋值,无警告且赋值成功 frame.at[0, 'B'] = pandas.DataFrame() print(frame)
或者使用loc配合列表索引,明确告诉pandas要将右侧的对象作为单个元素赋值:
frame.loc[[0], 'B'] = [pandas.DataFrame()]
这两种方式都能可靠地将DataFrame存储到目标单元格中,且不会触发警告。
内容的提问来源于stack exchange,提问作者Daniil Lantukhov
相关产品推荐
相关产品推荐

