What is correct syntax to swap column values for selected rows in a pandas data frame using just one line?
One way you could avoid alignment on column names would be to drop down to the underlying array via .values
:
In [33]: df
Out[33]:
L R VALUE
0 left right -1
1 right left 1
2 left right -1
3 right left 1
4 left right -1
5 right left 1
In [34]: df.loc[idx,['L','R']] = df.loc[idx,['R','L']].values
In [35]: df
Out[35]:
L R VALUE
0 left right -1
1 left right 1
2 left right -1
3 left right 1
4 left right -1
5 left right 1
The key thing to note here is that pandas attempts to automatically align rows and columns using the index and column names. Hence, you need to somehow tell pandas to ignore the column names here. One way is as @DSM does, by converting to a numpy array. Another way is to rename the columns:
>>> df.loc[idx] = df.loc[idx].rename(columns={'R':'L','L':'R'})
L R VALUE
0 left right -1
1 left right 1
2 left right -1
3 left right 1
4 left right -1
5 left right 1
You can also do this with np.select
and df.where
i.e
Option 1: np.select
df[['L','R']] = pd.np.select(df['VALUE'] == 1, df[['R','L']].values, df[['L','R']].values)
Option 2: df.where
df[['L','R']] = df[['R','L']].where(df['VALUE'] == 1, df[['L','R']].values)
Option 3: df.mask
df[['L','R']] = df[['L','R']].mask( df['VALUE'] == 1, df[['R','L']].values)
Output:
L R VALUE
0 left right -1
1 left right 1
2 left right -1
3 left right 1
4 left right -1
5 left right 1