Почему «SettingWithCopyWarning» возникает (по-видимому) непоследовательно?Python

Программы на Python
Anonymous
Почему «SettingWithCopyWarning» возникает (по-видимому) непоследовательно?

Сообщение Anonymous »

Настройка
Сначала мы импортируем pandas и numpy, а затем создаем 5000 строк x 10 столбцов pd.DataFrame под названием df

Код: Выделить всё

import pandas as pd
import numpy as np

# Generate non-trivial df
data = np.random.rand(5000, 10)
column_names = [f'col_{i}' for i in range(10)]
df = pd.DataFrame(data, columns=column_names)
Получаем предупреждение SettingWithCopyWarning
Затем мы берем df, выбираем 2 столбца и добавляем к ним новый столбец со статическим значением 10

Код: Выделить всё

foo = df
print(f"foo has type {type(foo)}\n")
bar = foo[["col_0", "col_1"]]
bar["new"] = 10
print(f"After modification bar has {type(bar)}\n\nbar is:\n{bar}")
Это дает результат

Код: Выделить всё

foo has type 

After modification bar has 

bar is:
col_0     col_1  new
0     0.837911  0.715060   10
...        ...       ...  ...
4999  0.684007  0.176949   10

[5000 rows x 3 columns]
C:\Users\vents\AppData\Local\Temp\ipykernel_5824\1295636698.py:5: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead

See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
bar["new"] = 10
Обратите внимание на предупреждение внизу.
Сделайте то же самое с другим df, но не получите SettingWithCopyWarning.
Теперь мы делаем то же самое, что и выше, но устанавливаем foo в тривиальную таблицу

Код: Выделить всё

foo = pd.DataFrame([["x",20.2,30], ["y",80,70]], columns=["col_0", "col_1", "col_2"])
print(f"foo has type {type(foo)}\n")
bar = foo[["col_0", "col_1"]]
bar["new"] = 10
print(f"After modification bar has {type(bar)}\n\nbar is:\n{bar}")
Теперь это дает результат

Код: Выделить всё

foo has type 

After modification bar has 

bar is:
col_0  col_1  new
0     x   20.2   10
1     y   80.0   10
У нас нет предупреждений.
Мое объяснение(?) и мысли
Насколько я понимаю, SettingWithCopyWarning означает, что существует неопределенность относительно того, является ли таблица копией или представлением. Так что, возможно, у pandas есть какая-то логика оптимизации: если таблица маленькая, она просто дает вам копию, потому что "о, какого черта, просто избавьте их от головной боли; их таблица крошечная, мы просто сделаем для них копию"??? Но тогда для большей таблицы он не хочет тратить оперативную память на копирование, поэтому требует от пользователей быть умнее?
Это мое лучшее предположение.
Мне просто не нравится общий совет: "О, просто используйте foo.loc[:, ["col_0", "col_1"] или foo[["col_0", "col_1"]].copy() и вы не получу ошибку", потому что я не уверен, что полностью понимаю проблему...
Например, какие другие части моего кода плохи, но мне (не)повезло, что я не получил предупреждение?
Из того, что я видел в Интернете, большинство настроек SettingWithCopyWarning часто выдаются, если вы берете подмножество данных, тип которых отличается от исходной таблицы, а затем пытаетесь сделать что-то к нему (например, foo[0]["col_0"], который сначала берет серию foo[0] а затем из нее дает столбец col_0).

Вернуться в «Python»