saikon
saikon

Reputation: 147

Pandas assign to chained .loc views (not copies) and SettingWithCopyWarning

There seems to be a lot of confusion around the .loc and SettingWithCopyWarning. In my case I could not find a solution to this situation from existing questions.

Currently I have a DF which I would like to filter with slices and then set values to these slices which propagate to the original. So I do not want a copy, I want the view which I modify.

Currently it works with this:

A0.loc[(A0['Pääkategoria'].isnull()) & (A0.Määrä < 0) & (A0.SaajaMaksaja.str.contains('|'.join(catfilter))), 'Pääkategoria'] = cat1

This will get quite complicated when there are lot of filters to be fullfilled. Is it possible to get views "incrementally" which I work on and then the set values to the view are propagated to the original DF A0?


Now I have the following which causes: SettingWithCopyWarning

A1 = A0.loc[(A0['Pääkategoria'].isnull() & (A0.Määrä < 0))]
A1.loc[A1.SaajaMaksaja.str.contains('|'.join(catfilter)), 'Pääkategoria'] = cat1

So it seems that the A1 is only a copy, not a slice. Slicing multiple times would allow me to do slices for different situations (> 0 for example)

Upvotes: 2

Views: 771

Answers (2)

Kasinath PS
Kasinath PS

Reputation: 46

try this one after importing pandas (as pd)

pd.options.mode.chained_assignment = None

just try

Upvotes: 0

jpp
jpp

Reputation: 164683

In my opinion, a much more readable solution which should not cause SettingWithCopyWarning is to calculate your partial mask as a separate step.

Then use the & operator once within pd.DataFrame.loc:

mask = A0['Pääkategoria'].isnull() & (A0.Määrä < 0)

A0.loc[mask & A1.SaajaMaksaja.str.contains('|'.join(catfilter)), 'Pääkategoria'] = cat1

Chaining loc indexers, as you noticed, is liable to raise SettingWithCopyWarning. But this chaining is not necessary to calculate the intersection of Boolean series.

Upvotes: 1

Related Questions