SettingWithCopyWarning in Pandas

The first thing you should understand is that SettingWithCopyWarning is a warning, and not an error. You can safely disable this warning with the following assignment.
pd.options.mode.chained_assignment = None
  1. None : ignoring the warning
  2. "warn" : printing a warning message
  3. "raise" : raising an exception

Chained Assignment

A chained assignment is used to assign values to a series of variables. The SettingWithCopyWarning was created to flag "chained assignment" operations. Example

Lets' create a DataFrame with values.

import pandas as pd import numpy as np df = pd.DataFrame() df['Item_name'] = ['Item_1', 'Item_2', 'Item_3','Item_4', 'Item_5', 'Item_6'] df['Price'] = [520, 120,340,650,220,780] df['Discount'] = [12, 18, 10,24,15,10] df
Item_name Price Discount 0 Item_1 520 12 1 Item_2 120 18 2 Item_3 340 10 3 Item_4 650 24 4 Item_5 220 15 5 Item_6 780 10

Retrieve the items whose price is greater than 500.

df[df.Price >= 500][['Item_name','Price','Discount']]
Item_name Price Discount 0 Item_1 520 12 3 Item_4 650 24 5 Item_6 780 10

Then, try to update Discount upto 50% whose Price is greater than 500.

df[df.Price >= 500]['Discount'] = 50
Then you will get the SettingWithCopyWarning warning:
how to fix settingwithcopywarning
The real problem behind the "SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame." warning is that it is generally difficult to predict whether a view or a copy is returned. Here the warning was raised because you have chained two indexing operations together. This is made easier to spot because you used [] (square brackets) twice, but the same would be true if we used other access methods such as .loc[] , .iloc[] and so on. Here, the chained operations are:
df[df.Price >= 500] ['Discount'] = 50
As mentioned in the warning "Try using .loc[row_indexer,col_indexer] = value instead", you can solve this issue by using df.loc[].
df.loc[df.Price >= 500, 'Discount'] = 50
Then you can see the DataFrame updated without any warning.
how to handle settingwithcopywarning

What really happend?

When you using df.loc[] ...
df.loc[df.Price >= 500, 'Discount'] = 50

It becomes...

df.__setitem__((df.Price >= 500, 'Discount'), 50)
In the above code, with a single __setitem__ call to DataFrame.

When you using....

df[df.Price >= 500]['Discount'] = 50

It becomes...

df.__getitem__(df.Price >= 500).__setitem__('Discount', 50)
Above code raised the SettingWithCopyWarning waring because depending on whether __getitem__ returned a view or a copy, the __setitem__ operation may not work.

DataFrame View Vs Copy

When filtering Pandas DataFrames , it is possible slice/index a frame to return either a view or a copy. A "View" is a view of the original data, so modifying the view may modify the original data. While, a "Copy" is a replication of data from the original, any changes made to the copy will not affect original data, and any changes made to the original data will not affect the copy.

How to suppress the SettingWithCopyWarning warning?

You can change the behaviour of SettingWithCopyWarning warning using pd.options.mode.chained_assignment with three option "raise"/"warn"/None .
  1. raise : raises a SettingWithCopyException.
  2. warn : issues a SettingWithCopyWarning (default).
  3. None : suppresses the warning.
pd.options.mode.chained_assignmen = None