Reputation: 575
I have a DataFrame like:
df = pd.DataFrame({"type":['pet', 'toy', 'toy', 'car'], 'symbol': ['A', 'B', 'C', 'D'], 'desc': [1, 2, 3, 4]})
df
Out[22]:
type symbol desc
0 pet A 1
1 toy B 2
2 toy C 3
3 car D 4
My goal is to swap the values of symbol
and desc
for the rows whose type
is toy
:
type symbol desc
0 pet A 1
1 toy 2 B # <-- B and 2 are swapped
2 toy 3 C # <-- C and 3 are swapped
3 car D 4
So I am going to take a slice first, then do the swap on the slice, but failed. My scripts, warnings and results are:
df[df['type']=='toy'][['symbol', 'desc']] = df[df['type']=='toy'][['desc', 'symbol']]
/anaconda3/lib/python3.8/site-packages/pandas/core/frame.py:3191: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
self[k1] = value[k2]
df
Out[31]:
type symbol desc
0 pet A 1
1 toy B 2 # <-- didn't work :(
2 toy C 3
3 car D 4
Is there any advice?
Upvotes: 1
Views: 199
Reputation: 23227
You can also use list(zip(...))
:
m = df['type']=='toy'
df.loc[m, ['symbol', 'desc']] = list(zip(df.loc[m, 'desc'], df.loc[m, 'symbol']))
Or simply use .values
:
m = df['type']=='toy'
df.loc[m, ['symbol', 'desc']] = df.loc[m, ['desc', 'symbol']].values
Result:
print(df)
type symbol desc
0 pet A 1
1 toy 2 B
2 toy 3 C
3 car D 4
Upvotes: 0
Reputation: 323346
Let us do
m = df.type=='toy'
l = ['symbol','desc']
df.loc[m,l] = df.loc[m,l[::-1]].values
df
Out[89]:
type symbol desc
0 pet A 1
1 toy 2 B
2 toy 3 C
3 car D 4
Or try with rename
m = df.type=='toy'
l = ['symbol','desc']
out = pd.concat([df[~m],df[m].rename(columns=dict(zip(l,l[::-1])))]).sort_index()
Upvotes: 3
Reputation: 1875
You can also use pandas where:
df[['symbol', 'desc']] = df[['desc', 'symbol']].where(df['type'] == 'toy',
df[['symbol', 'desc']].values)
Output:
type symbol desc
0 pet A 1
1 toy 2 B
2 toy 3 C
3 car D 4
Upvotes: 0
Reputation: 35676
Let's try something like:
import pandas as pd
df = pd.DataFrame(
{"type": ['pet', 'toy', 'toy', 'car'], 'symbol': ['A', 'B', 'C', 'D'],
'desc': [1, 2, 3, 4]})
m = df['type'] == 'toy'
df.loc[m, ['symbol', 'desc']] = df.loc[m, ['desc', 'symbol']].to_numpy()
print(df)
Output:
type symbol desc
0 pet A 1
1 toy 2 B
2 toy 3 C
3 car D 4
Use to_numpy() / values to prevent columns from matching to their old column names.
Upvotes: 1