Move / Shift Values ​​in Pandas Data Frame

Assuming an example of a df dataframe :

    A
0   4.3
1   75
2   8.5
3   4.0
4   98

      

I would need to move every value from column A

to every column - one value per column:

  • starting at the second value: go to the second column B

    ,
  • the third value for the third column C

    ,
  • etc.

Desired output:

    A     B    C   D   E
0   4.3  NaN  NaN NaN NaN
1   NaN   75  NaN NaN NaN
2   NaN  NaN  8.5 NaN NaN
3   NaN  NaN  NaN 4.0 NaN
4   NaN  NaN  NaN Nan  98

      

One idea was to copy each value to the second column and then delete it in the previous column, or to the value shift

from one column to another, but I'm not sure how to apply that ...

MWE

import pandas as pd
import numpy as np

df=pd.DataFrame(data=np.random.randint(0,100,(5,5)), columns=['A','B','C','D','E'])
df.iloc[:,1:] =np.nan

df.iloc[[1],[1]] = df.iloc[[1],[0]]
df.iloc[[1],[1]] = df.iloc[[1],[0]].shift(1,axis=1)

      

+3


source to share


2 answers


In [76]: import string

In [77]: r = pd.DataFrame(np.eye(len(df)), 
                          columns=list(string.ascii_uppercase[:len(df)])) \
               .replace(0, np.nan) * df.A.values

In [78]: r
Out[78]:
     A     B    C    D     E
0  4.3   NaN  NaN  NaN   NaN
1  NaN  75.0  NaN  NaN   NaN
2  NaN   NaN  8.5  NaN   NaN
3  NaN   NaN  NaN  4.0   NaN
4  NaN   NaN  NaN  NaN  98.0

      

or better:

In [11]: r = pd.DataFrame(index=df.index, columns=list(string.ascii_uppercase[:len(df)]))

In [12]: np.fill_diagonal(r.values, df.A)

In [13]: r
Out[13]:
     A    B    C    D    E
0  4.3  NaN  NaN  NaN  NaN
1  NaN   75  NaN  NaN  NaN
2  NaN  NaN  8.5  NaN  NaN
3  NaN  NaN  NaN    4  NaN
4  NaN  NaN  NaN  NaN   98

      

UPDATE:

how to "move" a single value

we can use the Series.shift method .



horizontal movement:

In [94]: r.loc[1] = r.loc[1].shift(3)

In [95]: r
Out[95]:
     A   B    C    D     E
0  4.3 NaN  NaN  NaN   NaN
1  NaN NaN  NaN  NaN  75.0
2  NaN NaN  8.5  NaN   NaN
3  NaN NaN  NaN  4.0   NaN
4  NaN NaN  NaN  NaN  98.0

      

move vertically:

In [96]: r.loc[:, 'D'] = r.loc[:, 'D'].shift(-2)

In [97]: r
Out[97]:
     A   B    C    D     E
0  4.3 NaN  NaN  NaN   NaN
1  NaN NaN  NaN  4.0  75.0
2  NaN NaN  8.5  NaN   NaN
3  NaN NaN  NaN  NaN   NaN
4  NaN NaN  NaN  NaN  98.0

      

NOTE. shift

will move the entire row / column , but as soon as we only have one value in each row / column this will work.

+5


source


>>> import pandas as pd
>>> import numpy as np
>>> df = pd.DataFrame({'A':[4.3, 75, 8.5, 4.0, 98]})
>>> df
      A
0   4.3
1  75.0
2   8.5
3   4.0
4  98.0


>>> diag_df = pd.DataFrame(np.diag(df.A), index=df.index, columns=['A', 'B', 'C', 'D', 'E'])
>>> diag_df.replace(0, np.nan, inplace=True)
>>> diag_df
     A     B    C    D     E
0  4.3   NaN  NaN  NaN   NaN
1  NaN  75.0  NaN  NaN   NaN
2  NaN   NaN  8.5  NaN   NaN
3  NaN   NaN  NaN  4.0   NaN
4  NaN   NaN  NaN  NaN  98.0

      



Keep in mind that if you have 0

a diagonal then it will be replaced with NaN

if you use the method replace

this way.

+3


source







All Articles