Reputation: 113
I want to calculate difference between 2 rows in a column to a new column
(Y(A1)/X(A1))-(Y(A1)/X(A1))/(Y(A1)/X(A1))*100% (3/52-1/41)/(1/41)*100% = 57.72%
The attached code is working but the last row is dropped for some reason
c = c.rename(lambda x: (x)*2+1)
c = c.map('{:,.2f}%'.format)
df['Z']=c
Expected result:
X Y Z
A1 41 1
A2 52 3 57.72%
B1 74 6
B2 74 4 -50.00%
C1 5 0
C2 5 0 nan%
D1 120 7
D2 131 7 -9.17%
What I actually get:
X Y Z
A1 41 1
A2 52 3 57.72%
B1 74 6
B2 74 4 -50.00%
C1 5 0
C2 5 0 nan%
D1 120 7
D2 131 7
Upvotes: 2
Views: 39
Reputation: 862641
Use GroupBy.pct_change
by groups for each 2 rows created by integer division of 1d array created by numpy.arange
:
print (np.arange(len(df)) // 2)
[0 0 1 1 2 2 3 3]
df['Z1'] = df['X'].div(df['Y']).groupby(np.arange(len(df)) // 2).pct_change().mul(-100)
print (df)
X Y Z Z1
A1 41 1 NaN NaN
A2 52 3 57.72% 57.723577
B1 74 6 NaN NaN
B2 74 4 -50.00% -50.000000
C1 5 0 NaN NaN
C2 5 0 nan% NaN
D1 120 7 NaN NaN
D2 131 7 -9.17% -9.166667
Another solution:
s1 = df['X'].div(df['Y'])
df['Z1'] = (1-s1[1::2] / s1[::2].values).mul(100)
print (df)
X Y Z Z1
A1 41 1 NaN NaN
A2 52 3 57.72% 57.723577
B1 74 6 NaN NaN
B2 74 4 -50.00% -50.000000
C1 5 0 NaN NaN
C2 5 0 nan% NaN
D1 120 7 NaN NaN
D2 131 7 -9.17% -9.166667
If need missing values for non matched values use map
with if-else
for avoid convert missing values to strings:
s = df['X'].div(df['Y']).groupby(np.arange(len(df)) // 2).pct_change().mul(-100)
df['Z1'] = s.map(lambda x: '{:,.2f}%'.format(x) if x == x else np.nan)
print (df)
X Y Z Z1
A1 41 1 NaN NaN
A2 52 3 57.72% 57.72%
B1 74 6 NaN NaN
B2 74 4 -50.00% -50.00%
C1 5 0 NaN NaN
C2 5 0 nan% NaN
D1 120 7 NaN NaN
D2 131 7 -9.17% -9.17%
Upvotes: 2