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.