1

I have a dataframe that looks as follows

import pandas as pd 
df = pd.DataFrame(data={"ID":[11,12,13,14,25],\
"Name":["Alice","Bob","Charlie", "Dan", "Erin"], "X":[1,0,0,0,0]})

   ID     Name  X
0  11    Alice  1
1  12      Bob  0
2  13  Charlie  0
3  14      Dan  0
4  25     Erin  0

I want to select the first row for which X is 0, and change the value to 1. I tried

df[df["X"]==0]["X"].iloc[0] = 1

But this doesn't seem to modify the dataframe df at all. This is odd to me since I do not get any error message, and since removing the =1 yields

>>> df[df["X"]==0]["X"].iloc[0]
 0

as expected.

I suspect that the conditioning creates a copy of the dataframe, and so the dataframe df simply never gets modified.

What would be the best way of accomplishing this to get

   ID     Name  X
0  11    Alice  1
1  12      Bob  1
2  13  Charlie  0
3  14      Dan  0
4  25     Erin  0

Of course this needs to be done systematically since I will need to iterate the process.

Thank you very much in advance for your help.

jpp
  • 159,742
  • 34
  • 281
  • 339
Zeta
  • 252
  • 2
  • 5

2 Answers2

2

I will using idxmax

df.loc[df.X.eq(0).idxmax(),'X']=1
df
Out[153]: 
   ID     Name  X
0  11    Alice  1
1  12      Bob  1
2  13  Charlie  0
3  14      Dan  0
4  25     Erin  0
BENY
  • 317,841
  • 20
  • 164
  • 234
0

Use at / iat for scalar setting

The difficulty arises because you wish to mix positional row indexing with label-based column indexing. Choose one and stick with it for rows and columns.

You can use labels throughout, similar to @Wen's solution but via at:

df.at[df['X'].eq(0).idxmax(), 'X'] = 1

Or you can integer positional indexing throughout via iat:

df.iat[df['X'].eq(0).values.argmax(), df.columns.get_loc('X')] = 1

Both solutions yield the same result. The former is likely more readable.

print(df)

   ID     Name  X
0  11    Alice  1
1  12      Bob  1
2  13  Charlie  0
3  14      Dan  0
4  25     Erin  0

pd.Series.idxmax / np.argmax are vectorised, but not particularly efficient. If efficiency is a concern, see Efficiently return the index of the first value satisfying condition in array.

jpp
  • 159,742
  • 34
  • 281
  • 339