【问题标题】:create numpy array in for loop without usage of concatenation在 for 循环中创建 numpy 数组而不使用连接
【发布时间】:2020-11-12 00:48:48
【问题描述】:

我正在创建一个具有多个 for 循环的模拟。 我的目标是创建一个包含所有值的 numpy 数组。我首先使用了 numpy.concatenate,因为它可以完成这项工作。不过,我读到 np.concatenate 非常慢,所以我正在寻找一种更快的方法来创建具有值的数组 我的代码:

import numpy as np
values = np.array([])
for n in [100,1000]:
    for m in [2,10,100]:
        for roh in [0.0,0.5,0.9]:
            values = np.concatenate((values,[n,m,roh,1,2])) 

值 1,2 只是样本值,对于这个问题并不重要。 那么有没有更快/更智能的方法来创建一个包含三重 for 循环的所有排列的 numpy 数组?

【问题讨论】:

    标签: python-3.x numpy concatenation


    【解决方案1】:

    itertools 会非常方便。例如

    (修改了这个答案,也解决了后续问题)

    import numpy as np
    import itertools
    n_list, m_list, rho_list = [100,1000], [2,10,100], [0.0,0.5,0.9]
    
    f1, f2 = lambda mat: 1, lambda mat: 2 # change accordingly
    
    def f(n, m, rho, f1, f2):
        distance_matrix = np.zeros((2, 2))
        ## replace accordingly
        return f1(distance_matrix), f2(distance_matrix)
    
    ff = lambda n, m, rho: f(n, m, rho, f1, f2) 
    values = np.array([[n, m, rho, *ff(n, m, rho)] for n, m, rho in itertools.product(n_list, m_list, rho_list)])
    

    *ff(...) 是将元组解包成两个单独的值。

    【讨论】:

    • 我的问题中的值 1 和 2 将根据 n、m、roh 计算。假设这些值将存储在变量“value1”和“value2”中。我也可以在您的答案中实现这些值吗?
    • 当然,给定您的两个函数f1f2 用于计算这些值,您可以使用values = np.array([[n, m, rho, f1(n, m, rho), f2(n, m, rho)] for n, m, rho in itertools.product(n_list, m_list, rho_list)])
    • 我测试了你和 Michael Sidorovs 的答案,并将我的测试结果作为答案发布。我仍然赞成您的答案作为解决我问题的答案
    • 假设每次 n,m,roh 迭代我想创建多个值数组,就像你展示的那样,但是数组中的函数 f1() 和 f2() 应该用于所有这些值数组取决于 distance_matrix(每次 n、m、roh 迭代创建)。这可能吗 ?所以为了澄清我有 18 个 n,m,roh 排列,这意味着 18 个不同的距离矩阵,其中将有多个具有函数 f1(距离矩阵)和 f2(距离矩阵)的值数组。我希望我的问题很清楚
    • 您可以将f1f2 合并为一个函数f,在其中组装距离矩阵,然后返回元组f1(distance_matrix), f2(distance_matrix)
    【解决方案2】:

    好的,感谢“Peter Meisrimel”和“Michael Sidorov”的回答。我自己尝试过,先创建一个空数组,然后将值插入到空数组中。我还实现了两个答案并测试了所有答案(包括串联)的性能。为了更好地查看性能差异,我大幅增加了我的 n、m、roh 的大小。这是我的代码:

    import numpy as np
    import itertools
    import time
    
    rows = np.arange(40)
    columns = np.arange(40)
    rohs = np.arange(40)
    num1 = np.array([1])
    num2 = np.array([2])
    
    start1 = time.time()
    asd1 = np.empty((64000,5),dtype=np.float32)
    iterator = 0
    for a in rows:
        for s in columns:
            for d in rohs:
                asd1[iterator] = a,s,d,1,2
                iterator += 1
    end1 = time.time()
    print("time with empty array: "+str(end1-start1))
    
    start2 = time.time()
    asd2 = np.array([a for a in itertools.product(rows,columns,rohs,num1,num2)])
    end2 = time.time()
    print("time with itertools: "+str(end2-start2))
    
    start3 = time.time()
    asd3 = np.array([[n,m,roh,1,2] for n in rows for m in columns for roh in rohs])
    end3 = time.time()
    print("time with normal np array: "+str(end3-start3))
    
    start4 = time.time()
    asd4 = np.array([])
    for i in rows:
        for j in columns:
            for k in rohs:
                asd4 = np.concatenate((asd4,[i,j,k,1,2]))
    end4 = time.time()
    print("time with concatenation: "+str(end4-start4))
    

    当我运行这段代码时,我得到了以下输出:

    time with empty array: 0.203110933303833
    time with itertools: 0.14061522483825684
    time with normal np array: 0.15624260902404785
    time with concatenation: 49.35244131088257
    

    因此得出结论,两个给定的答案都比串联方法快得多,而使用空数组的速度相对较快,使用 itertools 被证明是解决此问题的最快方法,差异随着排列数量的增加而增加。

    【讨论】:

      【解决方案3】:

      您可以通过以下方式进行:

      np.array([[n,m,roh,1,2] for n in [100,1000] for m in [2,10,100] for roh in [0.0,0.5,0.9]])
      

      干杯。

      【讨论】:

        猜你喜欢
        • 2019-09-11
        • 1970-01-01
        • 1970-01-01
        • 2018-11-13
        • 1970-01-01
        • 1970-01-01
        • 2017-05-07
        • 1970-01-01
        相关资源
        最近更新 更多