Swapping values in columns depending on value type in one of the columns

Viewed 118

Suppose I have the following pandas dataframe:

df = pd.DataFrame([['A','B'],[8,'s'],[5,'w'],['e',1],['n',3]])
print(df)

   0  1
0  A  B
1  8  s
2  5  w
3  e  1
4  n  3

If there is an integer in column 1, then I want to swap the value with the value from column 0, so in other words I want to produce this dataframe:

   0  1
0  A  B
1  8  s
2  5  w
3  1  e
4  3  n
2 Answers

Replace numbers from second column with mask by to_numeric with errors='coerce' and Series.notna:

m = pd.to_numeric(df[1], errors='coerce').notna()

Another solution with convert to strings by Series.astype and Series.str.isnumeric - but working only for integers:

m = df[1].astype(str).str.isnumeric()

And then replace by DataFrame.loc with DataFrame.values for numpy array for avoid columns alignment:

df.loc[m, [0, 1]] = df.loc[m, [1, 0]].values
print(df)
   0  1
0  A  B
1  8  s
2  5  w
3  1  e
4  3  n

Last if possible better is convert first row to columns names:

df.columns = df.iloc[0]
df = df.iloc[1:].rename_axis(None, axis=1)
print(df)
   A  B
1  8  s
2  5  w
3  1  e
4  3  n

or possible removing header=None in read_csv.

sorted

with a key that test for int

df.loc[:] = [
    sorted(t, key=lambda x: not isinstance(x, int))
    for t in zip(*map(df.get, df))
]

df

   0  1
0  A  B
1  8  s
2  5  w
3  1  e
4  3  n

You can be explicit with the columns if you'd like

df[[0, 1]] = [
    sorted(t, key=lambda x: not isinstance(x, int))
    for t in zip(df[0], df[1])
]
Related