代码之家  ›  专栏  ›  技术社区  ›  Raven Cheuk

将numpy数组放入列表pythonic中吗?

  •  0
  • Raven Cheuk  · 技术社区  · 7 年前

    我试图通过使用 get_slice 由我定义的函数。 然后我突然意识到我的代码太笨拙了,因为我的原始数据已经是 numpy 数组,然后我需要将它存储到 切块 功能。之后,当我读到 data_matrix ,我需要另一个列表来再次存储信息。

    代码运行良好,但是numpy数组和list之间来回的转换对我来说似乎不是pythonic。我不知道我做得是否正确。如果没有,如何更有效和更蟒蛇?

    这是我的代码:

    import numpy as np
    
    ##Artifical Data Generation##
    X_row1 = np.linspace(1,60,60,dtype=int) 
    X_row2 = np.linspace(101,160,60,dtype=int)
    X_row3 = np.linspace(1001,1060,60,dtype=int) 
    
    data_matrix = np.append(X_row1.reshape(1,-1),X_row2.reshape(1,-1),axis=0)
    data_matrix = np.append(data_matrix,X_row3.reshape(1,-1,),axis=0)
    ##---------End--------------##
    
    ##The function for generating time slice for sequence##
    def get_slice(X,windows=5, stride=1):
        x_slice = []
        for i in range(int(len(X)/stride)):
            if i*stride < len(X)-windows+1:
                x_slice.append(X[i*stride:i*stride+windows])
    
        return np.array(x_slice)
    ##---------End--------------##
    
    x_list = []
    for row in data_matrix:
        temp_data = get_slice(row) #getting time slice as numpy array
        x_list.append(temp_data) #appending the time slice into a list
    
    X = np.array(x_list) #Converting the list back to numpy array
    
    3 回复  |  直到 7 年前
        1
  •  1
  •   user2699    7 年前

    把这作为一个半完整的答案来回答你的两点——使代码更加“pythonic”和“efficient”。

    有很多方法可以编写代码,而且在numpy代码和使用的纯python代码之间总是有一个平衡点。 这主要是因为体验了numpy,了解了一些更高级的特性、代码运行的速度以及个人偏好。 个人偏好是最重要的-你需要能够理解你的代码做什么和修改它。 别担心什么是蟒蛇,或者更糟的是-神经。 找到一种适合你的编码风格(就像你看起来做的那样),不要停止学习。 你会学到一些技巧(比如@b.m.的答案用法),但在大多数情况下,这些技巧应该保存下来,以备不时之需。 大多数技巧往往需要额外的工作,或只适用于某些情况。

    这就引出了你问题的第二部分。 如何提高代码的效率。 第一步是建立基准。 真正地。 我很惊讶有这么多东西可以加速代码,而这些东西几乎没有改变它,甚至使它运行得更慢。 python的列表是高度优化的,在很多方面都有很好的性能(尽管stackoverflow上的许多用户仍然相信使用numpy可以神奇地使任何代码更快)。

    为了解决特定的问题,在大多数情况下,混合列表和数组是很好的。尤其是如果

    1. 您事先不知道数据的大小(列表的扩展效率更高)
    2. 您正在将大量视图创建到一个数组中(在这种情况下,数组列表通常比一个大数组便宜)
    3. 数据形状不规则(数组必须是正方形)

    在你的代码中,案例2适用。诡计 as_strided 也可以工作,在某些情况下可能更快,但是在您分析并知道这些情况之前,我会说您的代码已经足够好了。

        2
  •  0
  •   B. M.    7 年前

    混合列表和数组是非常必要的。只有数组原语才能有效地使用相同的数据:

    data_matrix=np.add.outer([0,100,1000],np.linspace(1,60,60,dtype=int))
    X=np.lib.stride_tricks.as_strided(data_matrix2,shape=(3, 56, 5),strides=(4*60,4,4))
    

    只是个风景。新的数组可以通过 X=X.copy() 是的。

        3
  •  -1
  •   justengel    7 年前

    添加到列表将很慢。尝试列表理解以生成numpy数组。

    像下面这样的东西

    import numpy as np
    
    ##Artifical Data Generation##
    X_row1 = np.linspace(1,60,60,dtype=int)
    X_row2 = np.linspace(101,160,60,dtype=int)
    X_row3 = np.linspace(1001,1060,60,dtype=int)
    
    data_matrix = np.append(X_row1.reshape(1,-1),X_row2.reshape(1,-1),axis=0)
    data_matrix = np.append(data_matrix,X_row3.reshape(1,-1,),axis=0)
    ##---------End--------------##
    
    ##The function for generating time slice for sequence##
    def get_slice(X,windows=5, stride=1):
        return np.array([X[i*stride:i*stride+windows]
                         for i in range(int(len(X)/stride))
                          if i*stride < len(X)-windows+1])
    ##---------End--------------##
    
    X = np.array([get_slice(row) for row in data_matrix])
    print(X)
    

    这可能很奇怪,因为你有一个numpy数组。如果你想要一个三维数组,这是非常好的。如果不需要三维数组,则可能需要vstack或追加数组。

    # X = np.array([get_slice(row) for row in data_matrix])
    X = np.vstack((get_slice(row) for row in data_matrix))
    

    列表理解速度

    我在Windows10上运行Python3.4.4。

    import timeit
    
    
    TEST_RUNS = 1000
    LIST_SIZE = 2000000
    
    
    def make_list():
        li = []
        for i in range(LIST_SIZE):
            li.append(i)
        return li
    
    
    def make_list_microopt():
        li = []
        append = li.append
        for i in range(LIST_SIZE):
            append(i)
        return li
    
    
    def make_list_comp():
        li = [i for i in range(LIST_SIZE)]
        return li
    
    
    print("List Append:", timeit.timeit(make_list, number=TEST_RUNS))
    print("List Comprehension:", timeit.timeit(make_list_comp, number=TEST_RUNS))
    print("List Append Micro-optimization:", timeit.timeit(make_list_microopt, number=TEST_RUNS))
    

    输出

    List Append: 222.00971377954895
    List Comprehension: 125.9705268094408
    List Append Micro-optimization: 157.25782340883387
    

    我对微观优化的帮助感到非常惊讶。不过,对于我的系统中的大列表,列表理解要快得多。