A fillna via chained indexing left the NaNs and printed SettingWithCopyWarning — what is the fix?
This is meant to fill missing price values with 0, but after it runs the NaNs are still there and pandas prints a SettingWithCopyWarning.
import pandas as pd
def fill_price(df: pd.DataFrame) -> pd.DataFrame:
df[df['price'].isna()]['price'] = 0
return df
Find and fix the error.
df[mask]['price'] = 0 is chained indexing: df[mask] builds a temporary copy, the write lands there, and df is untouched — so the NaNs stay and pandas warns. Fix it with one indexer: df.loc[df['price'].isna(), 'price'] = 0 (or .fillna). Rule: one .loc/.iloc per write.
- ✗Silencing the warning instead of fixing the lost write
- ✗Blaming
isna()or a missing.copy()rather than chained indexing - ✗Not knowing
.loc[mask, col]takes a boolean mask on the row axis
- →Why can pandas not tell whether
df[mask]is a view or a copy? - →When would
df.fillnabe preferable to the.locassignment here?
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.