Цепная индексация
В качестве документации и нескольких других ответов на этом сайте ( [1] , [2] ) предполагают, что цепная индексация считается плохой практикой, и ее следует избегать.
Поскольку, как представляется, не существует изящного способа назначения назначений с использованием целочисленной индексации на основе позиций (т. е. .iloc
) без нарушения правила индексации цепочки (по состоянию на pandas 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: ...
Кажетсяs 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
это кажется мне странным, хотя я не уверен, что это не так.
Однако есть старая ошибка с похожим поведением.
ОБНОВЛЕНИЕ
Согласно разработчикам ожидается вышеупомянутое поведение.