1

My Problem

I have a loop that creates a value for x in time period t based on x in time period t-1. The loop is really slow so i wanted to try and turn it into a function. I tried to use np.where with shift() but I had no joy. Any idea how i might be able to get around this problem?

Thanks!

My Code

import numpy as np
import pandas as pd

csv1 = pd.read_csv('y_list.csv', delimiter = ',')
df = pd.DataFrame(csv1)

df.loc[df.index[0], 'var'] = 0

for x in range(1,len(df.index)):
    if df["LAST"].iloc[x] > 0:
        df["var"].iloc[x] = ((df["var"].iloc[x - 1] * 2) + df["LAST"].iloc[x]) / 3
    else:
        df["var"].iloc[x] = (df["var"].iloc[x - 1] * 2) / 3 

df

Input Data

Dates,LAST
03/09/2018,-7
04/09/2018,5
05/09/2018,-4
06/09/2018,5
07/09/2018,-6
10/09/2018,6
11/09/2018,-7
12/09/2018,7
13/09/2018,-9

Output

Dates,LAST,var
03/09/2018,-7,0.000000
04/09/2018,5,1.666667
05/09/2018,-4,1.111111
06/09/2018,5,2.407407
07/09/2018,-6,1.604938
10/09/2018,6,3.069959
11/09/2018,-7,2.046639
12/09/2018,7,3.697759
13/09/2018,-9,2.465173

2 Answers2

1

You are looking at ewm:

arg = df.LAST.clip(lower=0)
arg.iloc[0] = 0
arg.ewm(alpha=1/3, adjust=False).mean()

Output:

0    0.000000
1    1.666667
2    1.111111
3    2.407407
4    1.604938
5    3.069959
6    2.046639
7    3.697759
8    2.465173
Name: LAST, dtype: float64
Quang Hoang
  • 146,074
  • 10
  • 56
  • 74
0

You can use df.shift to shift the dataframe be a default of 1 row, and convert the if-else block in to a vectorized np.where:

In [36]: df
Out[36]: 
        Dates  LAST  var
0  03/09/2018    -7  0.0
1  04/09/2018     5  1.7
2  05/09/2018    -4  1.1
3  06/09/2018     5  2.4
4  07/09/2018    -6  1.6
5  10/09/2018     6  3.1
6  11/09/2018    -7  2.0
7  12/09/2018     7  3.7
8  13/09/2018    -9  2.5

In [37]: (df.shift(1)['var']*2 + np.where(df['LAST']>0, df['LAST'], 0)) / 3
Out[37]: 
0         NaN
1    1.666667
2    1.133333
3    2.400000
4    1.600000
5    3.066667
6    2.066667
7    3.666667
8    2.466667
Name: var, dtype: float64
CT Zhu
  • 52,648
  • 17
  • 120
  • 133