Shany H.
Shany H.

Reputation: 113

Calculating column row based on 2 rows in another column

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

Answers (1)

jezrael
jezrael

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

Related Questions