27

I know there are a number of topics on this question, but none of the methods worked for me so I'm posting about my specific situation

I have a dataframe that looks like this:

data = pd.DataFrame([[1,0],[0,1],[1,0],[0,1]], columns=["sex", "split"])
data['sex'].replace(0, 'Female')
data['sex'].replace(1, 'Male')
data

What I want to do is replace all 0's in the sex column with 'Female', and all 1's with 'Male', but the values within the dataframe don't seem to change when I use the code above

Am I using replace() incorrectly? Or is there a better way to do conditional replacement of values?

Simon
  • 9,762
  • 15
  • 62
  • 119

5 Answers5

66

Yes, you are using it incorrectly, Series.replace() is not inplace operation by default, it returns the replaced dataframe/series, you need to assign it back to your dataFrame/Series for its effect to occur. Or if you need to do it inplace, you need to specify the inplace keyword argument as True Example -

data['sex'].replace(0, 'Female',inplace=True)
data['sex'].replace(1, 'Male',inplace=True)

Also, you can combine the above into a single replace function call by using list for both to_replace argument as well as value argument , Example -

data['sex'].replace([0,1],['Female','Male'],inplace=True)

Example/Demo -

In [10]: data = pd.DataFrame([[1,0],[0,1],[1,0],[0,1]], columns=["sex", "split"])

In [11]: data['sex'].replace([0,1],['Female','Male'],inplace=True)

In [12]: data
Out[12]:
      sex  split
0    Male      0
1  Female      1
2    Male      0
3  Female      1

You can also use a dictionary, Example -

In [15]: data = pd.DataFrame([[1,0],[0,1],[1,0],[0,1]], columns=["sex", "split"])

In [16]: data['sex'].replace({0:'Female',1:'Male'},inplace=True)

In [17]: data
Out[17]:
      sex  split
0    Male      0
1  Female      1
2    Male      0
3  Female      1
Anand S Kumar
  • 88,551
  • 18
  • 188
  • 176
  • 1
    Using a dictionary rather than two lists feels more natural, IMHO. – DSM Aug 08 '15 at 02:08
  • If I do something like that I get a `SettingWithCopyWarning: A value is trying to be set on a copy of a slice from a DataFrame`. – Stefan Falk Sep 17 '17 at 12:50
  • What is your code, maybe you are slicing the original dataframe as well (thereby creating a copy) and trying to set to that? – Anand S Kumar Sep 17 '17 at 20:13
10

You can also try using apply with get method of dictionary, seems to be little faster than replace:

data['sex'] = data['sex'].apply({1:'Male', 0:'Female'}.get)

Testing with timeit:

%%timeit
data['sex'].replace([0,1],['Female','Male'],inplace=True)

Result:

The slowest run took 5.83 times longer than the fastest. This could mean that an intermediate result is being cached.
1000 loops, best of 3: 510 µs per loop

Using apply:

%%timeit
data['sex'] = data['sex'].apply({1:'Male', 0:'Female'}.get)

Result:

The slowest run took 5.92 times longer than the fastest. This could mean that an intermediate result is being cached.
1000 loops, best of 3: 331 µs per loop

Note: apply with dictionary should be used if all the possible values of the columns in the dataframe are defined in the dictionary else, it will have empty for those not defined in dictionary.

niraj
  • 17,498
  • 4
  • 33
  • 48
2

Can try this too!
Create a dictionary of replacement values.

import pandas as pd
data = pd.DataFrame([[1,0],[0,1],[1,0],[0,1]], columns=["sex", "split"])

enter image description here

replace_dict= {0:'Female',1:'Male'}
print(replace_dict)

enter image description here

Use the map function for replacing values

data['sex']=data['sex'].map(replace_dict)

Output after replacing
enter image description here

abdul
  • 526
  • 1
  • 5
  • 10
0

You can also try using Numpy's select:

import numpy as np

data['sex'] = np.select(
    [data['sex'].eq(0), data['sex'].eq(1)], ['Female', 'Male'], default=np.nan
)

Output:

    sex     split
0   Male    0
1   Female  1
2   Male    0
3   Female  1

If neither 0 or 1 is found, NaN is returned.

rachwa
  • 1,805
  • 1
  • 14
  • 17
0

None of these answers worked for me but this did:

data.gender[data['gender'] == 'Male'] = 1
data.gender[data['gender'] == 'Female'] = 2
Eric Aya
  • 69,473
  • 35
  • 181
  • 253