Pandas conditional swap

I have a pandas dataframe as shown below:

Col1 Col2 Col3 0 A 7 NaN 1 B 16 NaN 1 B 16 15 

What I want to do is exchange Col2 for Col3, where Col3 is NaN . Based on other posts and answers on SO, I have this code:

 df[['Col2', 'Col3']] = df[['Col3', 'Col2']].where(df[['Col3']].isnull()) 

But this does not seem to work properly and gives me the following:

  Col1 Col2 Col3 0 A NaN NaN 1 B NaN NaN 1 B NaN NaN 

Is there something I am missing here?

Update: My desired result is as follows:

  Col1 Col2 Col3 0 A NaN 7 1 B NaN 16 1 B 16 15 

thanks

+6
source share
2 answers

You can use loc to exchange:

 df.loc[df['Col3'].isnull(), ['Col2', 'Col3']] = df.loc[df['Col3'].isnull(), ['Col3', 'Col2']].values 

Note that .values is required to ensure that the .values is done correctly, otherwise Pandas will try to align the names of indexes and columns, and no exchange will occur.

You can also just reassign each line separately if you think the code is cleaner:

 null_idx = df['Col3'].isnull() df.loc[null_idx, 'Col3'] = df['Col2'] df.loc[null_idx, 'Col2'] = np.nan 

Result:

  Col1 Col2 Col3 0 A NaN 7.0 1 B NaN 16.0 2 B 16.0 15.0 
+6
source

Try the following: (faster)

 df["Col3"], df["Col2"] = np.where(df['Col3'].isnull(), [df["Col2"], df["Col3"]], [df["Col3"], df["Col2"] ]) df Col1 Col2 Col3 0 A NaN 7.0 1 B NaN 16.0 1 B 16.0 15.0 %timeit df.loc[df['Col3'].isnull(), ['Col2', 'Col3']] = df.loc[df['Col3'].isnull(), ['Col3', 'Col2']].values 100 loops, best of 3: 2.68 ms per loop %timeit df["Col3"], df["Col2"] = np.where(df['Col3'].isnull(), [df["Col2"], df["Col3"]], [df["Col3"], df["Col2"] ]) 1000 loops, best of 3: 592 ยตs per loop 
+3
source

All Articles