fillna через цепочечную индексацию оставил NaN и напечатал SettingWithCopyWarning — как исправить?
Это должно заполнить пропуски в price нулём, но после запуска NaN остаются на месте, а pandas печатает SettingWithCopyWarning.
import pandas as pd
def fill_price(df: pd.DataFrame) -> pd.DataFrame:
df[df['price'].isna()]['price'] = 0
return df
Найдите и исправьте ошибку.
df[mask]['price'] = 0 — цепочечная индексация: df[mask] строит временную копию, запись идёт туда, а df не трогается — поэтому NaN остаются, и pandas предупреждает. Чинят одним индексатором: df.loc[df['price'].isna(), 'price'] = 0 (или .fillna). Правило: один .loc/.iloc на запись.
- ✗Глушить предупреждение вместо починки потерянной записи
- ✗Винить
isna()или отсутствие.copy(), а не цепочечную индексацию - ✗Не знать, что
.loc[mask, col]принимает булеву маску по строкам
- →Почему pandas не может знать,
df[mask]— это view или копия? - →Когда
df.fillnaпредпочтительнее присваивания через.loc?
df[df['price'].isna()]['price'] = 0 indexes twice. df[mask] returns a new temporary object, the ['price'] = 0 write goes into that temporary, and it is then discarded — the original df is untouched, so the NaNs survive and pandas raises SettingWithCopyWarning precisely because it cannot guarantee the write reaches the frame.
import pandas as pd
def fill_price(df: pd.DataFrame) -> pd.DataFrame:
df.loc[df['price'].isna(), 'price'] = 0
return df
.loc[row_mask, 'col'] selects rows and column in one indexing operation on the real frame, so the assignment sticks. df['price'] = df['price'].fillna(0) is an equally correct fix.