SettingWithCopyWarning in PandasThe 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
- None : ignoring the warning
- "warn" : printing a warning message
- "raise" : raising an exception
Chained AssignmentA 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'] = 50Then you will get the SettingWithCopyWarning warning:
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'] = 50As 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'] = 50Then you can see the DataFrame updated without any warning.
What really happend?When you using df.loc ...
df.loc[df.Price >= 500, 'Discount'] = 50
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
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 CopyWhen 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 .
- raise : raises a SettingWithCopyException.
- warn : issues a SettingWithCopyWarning (default).
- None : suppresses the warning.
pd.options.mode.chained_assignmen = None
- ImportError: No module named pandas
- UnicodeDecodeError while reading CSV file
- How to fix CParserError: Error tokenizing data
- ValueError: cannot reindex from a duplicate axis
- How to fix "Unnamed: 0" column in a pandas DataFrame
- ValueError: cannot convert float NaN to integer
- ValueError: Unknown label type: 'unknown'
- ValueError: Length of values does not match length of index
- ValueError: The truth value of an array with more than..