I am trying to use list comprehension to replace this for loop. My list is
test_list = [3, 4, 6, 3, 8, 4, 7, 8, 12, 14, 1, 6, 7, 3, 7, 8, 3, 3, 7]
The function is
import numpy as np
def ema(x, n):
x = np.array(x)
emaint = np.zeros(len(x))
k = 2 / float(n + 1)
emaint[0:n] = np.average(x[:n])
for i in range(n, len(x)):
emaint[i] = (x[i] * k) + (emaint[i - 1] * (1 - k))
return emaint
The result for if I call ema(test_list, 5) will be
[4.8 4.8 4.8 4.8 4.8 4.53333333 5.35555556 6.23703704 8.15802469 10.10534979 7.0702332 6.7134888 6.80899253 5.53932835 6.0262189 6.68414594 5.45609729 4.63739819 5.42493213]
I have tried this
import numpy as np
def ema_compr(x, n):
x = np.array(x)
emaint = np.zeros(len(x))
k = 2 / float(n + 1)
emaint[0:n] = np.average(x[:n])
emaint[n:] = [(x[i] * k) + (emaint[i - 1] * (1 - k)) for i in range(n, len(x))]
return emaint
however the result is different if I call ema_compr(test_list, 5):
[4.8 4.8 4.8 4.8 4.8 4.53333333 2.33333333 2.66666667 4. 4.66666667 0.33333333 2. 2.33333333 1. 2.33333333 2.66666667 1. 1. 2.33333333]
I'd recommend just using the ewma
function in Pandas:
import pandas as pd
def ema(x, n):
pd_x = pd.Series(x)
pd_x[:n] = pd_x[:n].mean()
return pd.ewma(pd_x, span=n, adjust=False).as_matrix()
Because your loop needs to keep a running state it cannot cleanly be transformed into a list comprehension, although hacks exist.
So if you want "something like" a list comprehension I recommend the next best thing: an accumulator.
from itertools import accumulate
def ema(x, n):
xx = n*[sum(x[:n])/n] + x[n:]
p, q = 2 / (n+1), (n-1) / (n+1)
return list(accumulate(xx, lambda a, b: q*a + p*b))
Gives:
ema(test_list, 5)
# [4.8, 4.8, 4.8, 4.8, 4.8, 4.533333333333333, 5.355555555555555, 6.2370370370370365, 8.158024691358024, 10.105349794238682, 7.070233196159121, 6.713488797439414, 6.808992531626275, 5.539328354417517, 6.026218902945011, 6.684145935296673, 5.456097290197782, 4.637398193465188, 5.424932128976792]
Here you go , you need to specify the indices there :
import numpy as np
test_list = [3, 4, 6, 3, 8, 4, 7, 8, 12, 14, 1, 6, 7, 3, 7, 8, 3, 3, 7]
def ema(x, n):
x = np.array(x)
emaint = np.zeros(len(x))
k = 2 / float(n + 1)
emaint[0:n] = np.average(x[:n])
for i in range(n, len(x)):
[emaint.__setitem__(i, ((x[i] * k) + (emaint[i - 1] * (1 - k)))) for i in range(n, len(x))]
return emaint
print(ema(test_list, 5))
output:
[ 4.8 4.8 4.8 4.8 4.8 4.53333333
5.35555556 6.23703704 8.15802469 10.10534979 7.0702332
6.7134888 6.80899253 5.53932835 6.0262189 6.68414594
5.45609729 4.63739819 5.42493213]
In your list comprehension , you are trying to use index emaint[i-1]
with out saving the array. In list comprehension it will be saved once it iterates through entire array
You can write for loop like this to set the element and can go to next iteration ( this is almost like your first solution)
for i in range(0,len(x)):
if i<=n:
emaint[i]=np.average(x[:n])
else:
emaint[i]=((x[i] * k) + (emaint[i - 1] * (1 - k)))
Or as suggested by Sebastian you can use Pandas
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.