I would like to repeatedly shift select columns of a a dataframe based on the number of shifts specified in array nShiftsPerCol. How to generate the output dataframe DFO that contains the columns with nonzero shifts specified and each of those columns shifted multiple times. Note, the first shift is zero or no shift. Append the shift number to the column name.
import pandas as pd
import numpy as np
df = pd.DataFrame({'A': [1, 2, 3, 4, 5], 'B': [2, 3, 4, 5, 6], 'C': [3, 4, 5, 6, 7]})
print(df)
nCols = df.shape[0]
nShiftsPerCol = np.zeros(nCols)
nShiftsPerCol[0]=3 # shift column A 3 times
nShiftsPerCol[2]=2 # shift column C 2 times
Original dataframe
A B C
0 1 2 3
1 2 3 4
2 3 4 5
3 4 5 6
4 5 6 7
Desired output
A_0 A_1 A_2 C_0 C_1
0 1 2 3 3 4
1 2 3 4 4 5
2 3 4 5 5 6
3 4 5 NA 6 7
4 5 NA NA 7 NA
First create Series with filtering out 0 values:
#for columns need shape[1]
nCols = df.shape[1]
nShiftsPerCol = np.zeros(nCols)
nShiftsPerCol[0]=3 # shift column A 3 times
nShiftsPerCol[2]=2 # shift column C 2 times
print (nShiftsPerCol)
s = pd.Series(nShiftsPerCol, df.columns).astype(int)
s = s[s!=0]
print (s)
A 3
C 2
dtype: int32
and then loop and create new columns:
for i, x in s.items():
for y in range(x):
df['{}_{}'.format(i, y)] = df[i].shift(-y)
print (df)
A B C A_0 A_1 A_2 C_0 C_1
0 1 2 3 1 2.0 3.0 3 4.0
1 2 3 4 2 3.0 4.0 4 5.0
2 3 4 5 3 4.0 5.0 5 6.0
3 4 5 6 4 5.0 NaN 6 7.0
4 5 6 7 5 NaN NaN 7 NaN
Another solution for store columns names and shift number is list of tuples:
L = list(zip(df.columns, nShiftsPerCol.astype(int)))
L = [x for x in L if x[1] != 0]
print (L)
[('A', 3), ('C', 2)]
for i, x in L:
for y in range(x):
df['{}_{}'.format(i, y)] = df[i].shift(-y)
print (df)
A B C A_0 A_1 A_2 C_0 C_1
0 1 2 3 1 2.0 3.0 3 4.0
1 2 3 4 2 3.0 4.0 4 5.0
2 3 4 5 3 4.0 5.0 5 6.0
3 4 5 6 4 5.0 NaN 6 7.0
4 5 6 7 5 NaN NaN 7 NaN
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With