How to create "Column B" from "Column A"?
Column A Column B
0 1.0 1.0
1 NaN NaN
2 NaN NaN
3 NaN 1.0
4 NaN 2.0
5 NaN 3.0
6 NaN 4.0
7 5.0 5.0
8 NaN NaN
9 NaN NaN
10 NaN NaN
11 NaN 1.0
12 NaN 2.0
13 3.0 3.0
14 NaN NaN
15 NaN 1.0
16 NaN 2.0
17 NaN 3.0
18 4.0 4.0
>Solution :
Assuming empty cells are NaNs, you can use a custom groupby operation with a descending cumcount and transform('last'):
# group by successive NaNs ending on a non-NaN
g = df.groupby(df.loc[::-1, 'Column A'].notna().cumsum())['Column A']
# compute the descending cumcount, subtract from original value
s = g.transform('last').sub(g.cumcount(ascending=False))
# keep only strictly positive values
df['Column B'] = s.where(s.gt(0))
Output:
Column A Column B
0 1.0 1.0
1 NaN NaN
2 NaN NaN
3 NaN 1.0
4 NaN 2.0
5 NaN 3.0
6 NaN 4.0
7 5.0 5.0
8 NaN NaN
9 NaN NaN
10 NaN NaN
11 NaN 1.0
12 NaN 2.0
13 3.0 3.0
14 NaN NaN
15 NaN 1.0
16 NaN 2.0
17 NaN 3.0
18 4.0 4.0
Intermediates:
Column A Column B group cumcount last s s>0
0 1.0 1.0 4 0 1.0 1.0 True
1 NaN NaN 3 6 5.0 -1.0 False
2 NaN NaN 3 5 5.0 0.0 False
3 NaN 1.0 3 4 5.0 1.0 True
4 NaN 2.0 3 3 5.0 2.0 True
5 NaN 3.0 3 2 5.0 3.0 True
6 NaN 4.0 3 1 5.0 4.0 True
7 5.0 5.0 3 0 5.0 5.0 True
8 NaN NaN 2 5 3.0 -2.0 False
9 NaN NaN 2 4 3.0 -1.0 False
10 NaN NaN 2 3 3.0 0.0 False
11 NaN 1.0 2 2 3.0 1.0 True
12 NaN 2.0 2 1 3.0 2.0 True
13 3.0 3.0 2 0 3.0 3.0 True
14 NaN NaN 1 4 4.0 0.0 False
15 NaN 1.0 1 3 4.0 1.0 True
16 NaN 2.0 1 2 4.0 2.0 True
17 NaN 3.0 1 1 4.0 3.0 True
18 4.0 4.0 1 0 4.0 4.0 True