datarekha
Pandas & Data Wrangling Medium Asked at AirbnbAsked at LinkedInAsked at Stripe

What causes SettingWithCopyWarning in pandas and how do you fix it?

The short answer

SettingWithCopyWarning fires when you try to set a value on what pandas suspects is a copy of a slice rather than the original DataFrame, so the write may silently fail. The fix is to always use .loc on the original DataFrame for assignments, or call .copy() explicitly when you intend to work on a detached copy.

How to think about it

What’s actually happening

This is one of the most confusing pandas gotchas because the warning is not always an error — sometimes the write succeeds anyway. The issue is uncertainty: pandas doesn’t always know whether a slice shares memory with the original DataFrame (a view) or is an independent copy. When you chain two indexing operations like df[mask][col] = value, the first [] creates an intermediate object, and the second [] tries to write to it. If that intermediate is a copy, your write disappears silently.

The ambiguity exists because pandas sometimes returns views (same memory, fast) and sometimes returns copies (safe but separate), depending on the operation and the underlying memory layout. You cannot reliably predict which one you’ll get.

The fix: a single .loc call

The rule is simple: one [] to locate, one assignment. Never chain two [][] with an assignment.

The two intended patterns

There are really only two valid patterns:

Pattern 1 — modify the original DataFrame:

df.loc[condition, "column"] = new_value

Pattern 2 — work on an intentional copy:

subset = df[condition].copy()
subset["column"] = new_value

If you’re in situation 1, use .loc. If you’re in situation 2, call .copy() explicitly. The warning disappears in both cases because your intent is clear.

pandas 2.0+ Copy-on-Write

pandas 2.0 introduced opt-in Copy-on-Write semantics. Under CoW, every subset is always a copy, and chained writes have no effect on the original — which means the silent data corruption goes away. In pandas 3.0 this becomes the default behavior.

# Enable today for forward-compatible code
pd.options.mode.copy_on_write = True

With CoW enabled, df[mask]["col"] = value simply does nothing to df, turning a silent bug into an obvious no-op. Migrating to explicit .loc assignments makes your code correct both with and without CoW.

Learn it properly SettingWithCopyWarning — fixed

Keep practising

All Pandas & Data Wrangling questions

Explore further

Skip to content