61

List with attributes of persons loaded into pandas dataframe df2. For cleanup I want to replace value zero (0 or '0') by np.nan.

df2.dtypes

ID                   object
Name                 object
Weight              float64
Height              float64
BootSize             object
SuitSize             object
Type                 object
dtype: object

Working code to set value zero to np.nan:

df2.loc[df2['Weight'] == 0,'Weight'] = np.nan
df2.loc[df2['Height'] == 0,'Height'] = np.nan
df2.loc[df2['BootSize'] == '0','BootSize'] = np.nan
df2.loc[df2['SuitSize'] == '0','SuitSize'] = np.nan

Believe this can be done in a similar/shorter way:

df2[["Weight","Height","BootSize","SuitSize"]].astype(str).replace('0',np.nan)

However the above does not work. The zero's remain in df2. How to tackle this?

DannyDannyDanny
  • 838
  • 9
  • 26
Wouter Dunnes
  • 635
  • 1
  • 5
  • 10

7 Answers7

117

I think you need replace by dict:

cols = ["Weight","Height","BootSize","SuitSize","Type"]
df2[cols] = df2[cols].replace({'0':np.nan, 0:np.nan})
jezrael
  • 822,522
  • 95
  • 1,334
  • 1,252
  • 1
    I wonder why this solution works, while ```df2[cols].replace({'0':np.nan, 0:np.nan}, inplace=True)``` gives an error `A value is trying to be set on a copy of a slice from a DataFrame`? – Alexandr Kapshuk Sep 27 '19 at 16:38
  • It's not an error. It's just a warning. Basically, there could be memory issues there. – Bob Feb 07 '20 at 05:45
  • @M.Mariscal - Use `.replace({'.':'')` – jezrael Feb 10 '20 at 10:32
  • Doesnt work, my code is: cols = ['Total', 'uno', 'dos'] df[cols] = df[cols].replace({'.':''}) The problem is the to_csv i can see the point but because its thousands, but there is no point... the csv is a mess and i need to sort it ascend but cannot find the correct way – M. Mariscal Feb 10 '20 at 10:37
10

You could use the 'replace' method and pass the values that you want to replace in a list as the first parameter along with the desired one as the second parameter:

cols = ["Weight","Height","BootSize","SuitSize","Type"]
df2[cols] = df2[cols].replace(['0', 0], np.nan)
christk
  • 834
  • 11
  • 23
5

Try:

df2.replace(to_replace={
             'Weight':{0:np.nan}, 
             'Height':{0:np.nan},
             'BootSize':{'0':np.nan},
             'SuitSize':{'0':np.nan},
                 })
Myccha
  • 961
  • 1
  • 11
  • 20
  • 1
    this is the cleanest solution IMO. You don't need to pass it in as a kwarg either. Just the dict is fine. For reference -> https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.replace.html , the **dict-like `to_replace`** section – Nick Brady Dec 14 '20 at 22:11
3
data['amount']=data['amount'].replace(0, np.nan)
data['duration']=data['duration'].replace(0, np.nan)
Ayyasamy
  • 149
  • 1
  • 13
3

in column "age", replace zero with blanks

df['age'].replace(['0', 0'], '', inplace=True)

Replace zero with nan for single column

df['age'] = df['age'].replace(0, np.nan)

Replace zero with nan for multiple columns

cols = ["Glucose", "BloodPressure", "SkinThickness", "Insulin", "BMI"]

df[cols] = df[cols].replace(['0', 0], np.nan)

Replace zero with nan for dataframe

df.replace(0, np.nan, inplace=True)
1

If you just want to o replace the zeros in whole dataframe, you can directly replace them without specifying any columns:

df = df.replace({0:pd.NA})
Hamza
  • 5,373
  • 3
  • 28
  • 43
0

Another alternative way:

cols = ["Weight","Height","BootSize","SuitSize","Type"]
df2[cols] = df2[cols].mask(df2[cols].eq(0) | df2[cols].eq('0'))
Zhongbo Chen
  • 493
  • 4
  • 12