【问题标题】:How to create a list comprehension for this for loop如何为此 for 循环创建列表理解
【发布时间】:2017-12-22 04:03:58
【问题描述】:

我正在尝试使用列表推导来替换这个 for 循环。我的清单是

test_list = [3, 4, 6, 3, 8, 4, 7, 8, 12, 14, 1, 6, 7, 3, 7, 8, 3, 3, 7]

功能是

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

如果我调用 ema(test_list, 5) 的结果将是

[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]

我试过了

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

但是,如果我调用 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]
  1. 我想知道是否可以理解列表。
  2. 列表理解的结果是否不同,因为我要访问非创建的元素?

【问题讨论】:

  • x 和 n 的值是多少。我认为 x 是“test_list”。 n呢?
  • 他在他的问题中说ema_compr(test_list, 5) 的结果是什么。

标签: python list list-comprehension


【解决方案1】:

因为你的循环需要保持一个运行状态,它不能干净地转换成一个列表理解,尽管hacks 存在。

因此,如果您想要“类似”列表理解,我推荐下一个最好的东西:累加器。

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))

给予:

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]

【讨论】:

    【解决方案2】:

    我建议只在 Pandas 中使用 ewma 函数:

    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()
    

    【讨论】:

      【解决方案3】:

      给你,你需要在那里指定索引:

      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))
      

      输出:

      [  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]
      

      【讨论】:

        【解决方案4】:

        在您的列表理解中,您尝试使用索引 emaint[i-1] 而不保存数组。在列表理解中,它会在遍历整个数组时被保存

        您可以像这样编写 for 循环来设置元素并可以进行下一次迭代(这几乎就像您的第一个解决方案)

        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)))
        

        或者按照 Sebastian 的建议,您可以使用 Pandas

        【讨论】:

        • 谢谢。你是对的,我试图避免 if.. else 而你的回答是我的出发点。当我试图提高绘图速度时,我将第一部分移到循环之外。我尝试@sebastian 回答,但速度有点慢。我想我应该在我的问题中提到速度因素。
        猜你喜欢
        • 2010-10-01
        • 2017-11-23
        • 2022-01-12
        • 1970-01-01
        • 1970-01-01
        • 2020-09-13
        • 2022-10-07
        • 2019-03-21
        相关资源
        最近更新 更多