1

I want to set an entire column to a single string value. When doing so I get the (ever so popular) SettingWithCopy. I've tried to search SO before posting about this specific issue.

import pandas as pd
import numpy as np
dfp = pd.DataFrame({'A' : [1,21,8,44,np.NaN,6,75,8,44,999], 
                    'B' : [1,1,3,5,0,0,np.NaN,9,np.NaN,0], 
                    'C' : ['AA1233445','AA1233445', 'rmacy','Idaho Rx','Ab123455','TV192837','RX','Ohio Drugs','RX12345','USA Pharma'], 
                    'D' : [123456,123456,1234567,12345678,12345,12345,12345678,123456789,1234567,np.NaN],
                    'E' : ['Assign','Assign','Hello','Ugly','Appreciate','Undo','Testing','Unicycle','Pharma','Unicorn',]})
print(dfp)

new_df_to_show_copy = dfp.loc[(dfp['A']>100) |(dfp['E']=='Unicorn')]
new_df_to_show_copy['Reason'] = 'what is with the copy warning'

Now I can get rid of the warning with

new_df_to_show_copy = dfp.loc[(dfp['A']>100) |(dfp['E']=='Unicorn')].copy() <--Notice copy()
new_df_to_show_copy['Reason'] = 'what is with the copy warning'

And I know I can get rid of the warning with pd.options.mode.chained_assignment = None but I feel like that's "cheating". I'm looking at the documentation, but can't find a minimal way for setting an entire column to a single value without adding .copy() or suppressing the warning. What's the best way to do that?

MattR
  • 4,887
  • 9
  • 40
  • 67
  • It doesn't look to me like setting the entire column has anything to do with the problem. The problem is setting values at all on a copy created in a way that people often don't realize makes a copy. – user2357112 Jun 09 '17 at 20:48
  • I agree that setting the entire column is not the problem. Was just wondering if there was a way to do so without enacting the warning. I'm not even saying the warning is a bad thing, but just curious! – MattR Jun 09 '17 at 20:59
  • 1
    There's an answer to a similar question here: https://stackoverflow.com/a/39798005/7306999 – Xukrao Jun 09 '17 at 21:21
  • I'm not sitting in front of a computer right now, but what if you use `new_df_to_show_copy.loc[:,'Reason'] = '...'` – elPastor Jun 10 '17 at 06:37
  • Sorry I have not responded lately. Been busy on more important projects. @pshep123, your example returns the same warning. I thought that would work as well! – MattR Jun 16 '17 at 12:56

1 Answers1

0

I was working on a similar requirement earlier today and I came across assign. I got rid of the copy warning without using pd.options.mode.chained_assignment = None. Here was my solution:

new_df_to_show_copy = dfp.loc[(dfp['A']>100) |(dfp['E']=='Unicorn')]
new_df_to_show_copy = new_df_to_show_copy.assign(Reason = 'what is with the copy warning')

# output:

       A    B           C   D        E                         Reason
9  999.0  0.0  USA Pharma NaN  Unicorn  what is with the copy warning    

assign will leave a copy of the dataframe, and there is no inplace=True parameter. so just reassigning the value worked for me.

MattR
  • 4,887
  • 9
  • 40
  • 67