链索引
正如documentation 和本网站上的其他几个答案([1]、[2])所建议的那样,链索引被认为是不好的做法,应该避免。
由于似乎没有一种优雅的方式来使用基于整数位置的索引(即.iloc)而不违反链索引规则(从熊猫v0.23.4开始),建议尽可能使用基于标签的索引(即.loc)进行分配。
但是,如果您绝对需要按行号访问数据,您可以
df.iloc[-1, df.columns.get_loc('c')] = 42
或
df.iloc[[-1, 1], df.columns.get_indexer(['a', 'c'])] = 42
熊猫行为古怪
据我了解,您在尝试人为地重现错误时期待警告是绝对正确的。
到目前为止,我发现它取决于数据框的构造方式
df = pd.DataFrame({'a': [4, 5, 6], 'c': [3, 2, 1]})
df.iloc[-1]['c'] = 42 # no warning
df = pd.DataFrame({'a': ['x', 'y', 'z'], 'c': ['t', 'u', 'v']})
df.iloc[-1]['c'] = 'f' # no warning
df = pd.DataFrame({'a': ['x', 'y', 'z'], 'c': [3, 2, 1]})
df.iloc[-1]['c'] = 42 # SettingWithCopyWarning: ...
似乎pandas(至少v0.23.4)在链分配[3]时处理混合类型和单一类型数据帧的方式不同
def _check_is_chained_assignment_possible(self):
"""
Check if we are a view, have a cacher, and are of mixed type.
If so, then force a setitem_copy check.
Should be called just near setting a value
Will return a boolean if it we are a view and are cached, but a
single-dtype meaning that the cacher should be updated following
setting.
"""
if self._is_view and self._is_cached:
ref = self._get_cacher()
if ref is not None and ref._is_mixed_type:
self._check_setitem_copy(stacklevel=4, t='referant',
force=True)
return True
elif self._is_copy:
self._check_setitem_copy(stacklevel=4, t='referant')
return False
这对我来说真的很奇怪,虽然我不确定它是否不是预期的。
但是,有一个旧的bug 具有类似的行为。
更新
根据developers,上述行为是预期的。