简体   繁体   中英

Need help in calculating Symmetric percentage change on pandas dataframe - python

I have a dataframe 'df' with data below. I need to perform symmetric percentage change(formula below) on PX_LAST column.

xt = 200 * (X[t] - X[t-1])/(X[t] + X[t-1])

My Code:

z = []  
for j in range(1, len(df.index)):
    z.append((df.iloc[j, 1] - df.iloc[j - 1, 1]) / (df.iloc[j, 1] + df.iloc[j - 1, 1]) * 200.00)

This works fine and its returns list as Output. It there any better way to perform this calculation and return output as dataframe.

        date             PX_LAST       
0      2011-01-31           10.9    
1      2011-02-28           10.5    
2      2011-03-31           11.2  
3      2011-04-30            4.9   
4      2011-05-31           24.3  
5      2011-06-30            8.4  
6      2011-07-31           37.2  
7      2011-08-31           93.2  

Expected output in dataframe:

0      Nan
1      -3.73831
2      6.45161
3     -78.2608
4      132.8767
5     -97.24770
6      85.88957
7     -158.4615

Thanks!

Option 1

p = df.PX_LAST
(p.diff() / p.rolling(2).sum() * 200).fillna(0)

0      0.000000
1     -3.738318
2      6.451613
3    -78.260870
4    132.876712
5    -97.247706
6    126.315789
7     85.889571
Name: PX_LAST, dtype: float64

p = df.PX_LAST
df.assign(SymPct=(p.diff() / p.rolling(2).sum() * 200).fillna(0))

         date  PX_LAST      SymPct
0  2011-01-31     10.9    0.000000
1  2011-02-28     10.5   -3.738318
2  2011-03-31     11.2    6.451613
3  2011-04-30      4.9  -78.260870
4  2011-05-31     24.3  132.876712
5  2011-06-30      8.4  -97.247706
6  2011-07-31     37.2  126.315789
7  2011-08-31     93.2   85.889571

Option 2
Numpy approach

p = df.PX_LAST.values
np.diff(p) / (p[:-1] + p[1:]) * 200

array([  -3.73831776,    6.4516129 ,  -78.26086957,  132.87671233,
        -97.24770642,  126.31578947,   85.88957055])

p = df.PX_LAST.values
df.assign(SymPct=np.append(0, np.diff(p) / (p[:-1] + p[1:]) * 200)

         date  PX_LAST      SymPct
0  2011-01-31     10.9    0.000000
1  2011-02-28     10.5   -3.738318
2  2011-03-31     11.2    6.451613
3  2011-04-30      4.9  -78.260870
4  2011-05-31     24.3  132.876712
5  2011-06-30      8.4  -97.247706
6  2011-07-31     37.2  126.315789
7  2011-08-31     93.2   85.889571

Option 3
A little more elegant

p = df.PX_LAST.values
t0, t1 = p[:-1], p[1:]
df.assign(SymPct=np.append(0, (t1 - t0) / (t1 + t0) * 200))

         date  PX_LAST      SymPct
0  2011-01-31     10.9    0.000000
1  2011-02-28     10.5   -3.738318
2  2011-03-31     11.2    6.451613
3  2011-04-30      4.9  -78.260870
4  2011-05-31     24.3  132.876712
5  2011-06-30      8.4  -97.247706
6  2011-07-31     37.2  126.315789
7  2011-08-31     93.2   85.889571

Option 1] Use transform

In [517]: df.PX_LAST.transform(lambda x: 200*(x - x.shift())/(x + x.shift()))
Out[517]:
0           NaN
1     -3.738318
2      6.451613
3    -78.260870
4    132.876712
5    -97.247706
6    126.315789
7     85.889571
Name: PX_LAST, dtype: float64

Option 2] Vectorize

In [522]: px = df.PX_LAST

In [523]: pxs = df.PX_LAST.shift()

In [524]: 200 * (px - pxs)/(px + pxs)
Out[524]:
0           NaN
1     -3.738318
2      6.451613
3    -78.260870
4    132.876712
5    -97.247706
6    126.315789
7     85.889571
Name: PX_LAST, dtype: float64

Return new dataframe with result

In [525]: df.assign(SymPct=200 * (px - pxs)/(px + pxs))
Out[525]:
         date  PX_LAST      SymPct
0  2011-01-31     10.9         NaN
1  2011-02-28     10.5   -3.738318
2  2011-03-31     11.2    6.451613
3  2011-04-30      4.9  -78.260870
4  2011-05-31     24.3  132.876712
5  2011-06-30      8.4  -97.247706
6  2011-07-31     37.2  126.315789
7  2011-08-31     93.2   85.889571

Or, add to existing df

In [527]: df['SymPct'] = 200 * (px - pxs)/(px + pxs)

In [528]: df
Out[528]:
         date  PX_LAST      SymPct
0  2011-01-31     10.9         NaN
1  2011-02-28     10.5   -3.738318
2  2011-03-31     11.2    6.451613
3  2011-04-30      4.9  -78.260870
4  2011-05-31     24.3  132.876712
5  2011-06-30      8.4  -97.247706
6  2011-07-31     37.2  126.315789
7  2011-08-31     93.2   85.889571

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM