【问题标题】:How to speed up 2D arrays in 2D array in python?如何在python中加速二维数组中的二维数组?
【发布时间】:2020-12-04 06:47:56
【问题描述】:

我正在研究如何加快我的一项功能。该函数使用多个相同大小的二维数组调用。我想将它们组合成最后两个维度为 3x3 的 4D,然后得到整个数组的特征值。

我已经设法使用两个嵌套的for 循环来做到这一点,但它比我想要的要慢一些,那么有什么好方法可以加快代码速度吗?

def principal(xx, xy, xz, yy, yz, zz):

    import numpy as np

    xx = np.array(xx)
    xy = np.array(xy)
    xz = np.array(xz)
    yy = np.array(yy)
    yz = np.array(yz)
    zz = np.array(zz)

    size = np.shape(xx)
    Princ = np.empty((size[1], size[0], 3, 3))
    for j in range(size[1]):
        for i in range(size[0]):
            Princ[j, i, :, :] = np.array([[xx[i, j], xy[i, j], xz[i, j]],
                                          [xy[i, j], yy[i, j], yz[i, j]],
                                          [xz[i, j], yz[i, j], zz[i, j]]])
    Princ = np.linalg.eigvalsh(Princ)

    return Princ


import numpy as np

number_arrays_1 = 3
number_arrays_2 = 4

xx = np.ones((number_arrays_1, number_arrays_2))*80
xy = np.ones((number_arrays_1, number_arrays_2))*30
xz = np.ones((number_arrays_1, number_arrays_2))*0
yy = np.ones((number_arrays_1, number_arrays_2))*40
yz = np.ones((number_arrays_1, number_arrays_2))*0
zz = np.ones((number_arrays_1, number_arrays_2))*60

Princ = principal(xx, xy, xz, yy, yz, zz)
print(Princ)

我使用xx = np.array(xx) 进行转换的原因是,在较大的程序中,我将 pandas 数据帧而不是 numpy 数组传递给函数。

【问题讨论】:

  • 您正在为每个函数调用导入 numpy 2 次。您应该将它们移动到脚本的顶部
  • 我定义的函数主体通常位于一个单独的文件中,然后我将其导入主文件以供使用。我相信我必须导入我定义的每个函数中使用的模块,或者这不是真的吗?
  • @DogukanAltay,额外的导入不是问题。
  • xx 等总是np.ones(....)*c 吗?还是只是为了这个例子方便?
  • 只是在这个例子中,它们将是非常不同的,因为它们是模拟输出的。只是为了让我可以看到给出了正确的值(我知道最后评估的特征值是什么)

标签: python arrays performance numpy vectorization


【解决方案1】:

这看起来像一个简单的堆栈和重塑操作:

def principal(xx, xy, xz, yy, yz, zz):
    princ = np.stack((xx.T, xy.T, xz.T, xy.T, yy.T, yz.T, xz.T, yz.T, zz.T), axis=-1).reshape(*xx.shape[::-1], 3, 3)
    return = np.linalg.eigvalsh(princ)

如果输入已经是数组,则无需在输入上显式调用 np.array。数据帧上的xx.values() 应返回 numpy 值。

另一种方法是构建数组,然后将 3x3 维度换到后面。这可能会降低效率,因为第一种方法使 3x3 维度连续,而这种方法没有:

princ = np.array([[xx, xy, xz], [xy, yy, yz], [xz, yz, zz]]).T

不是很相关,但您可以像这样更快地生成数组:

target_shape = (3, 4)
values = np.array([80, 30, 0, 40, 0, 60])
xx, xy, xz, yy, yz, zz = np.full((6, *target_shape), values.reshape(-1, 1, 1))

事实上,如果您的数据允许,您甚至可以节省拆包:

data = np.full((6, *target_shape), values.reshape(-1, 1, 1))
principal(*data)

【讨论】:

  • 非常感谢,第一种堆叠然后重塑的方法几乎奏效了,但我不得不转置 xx、xy 等以使其成为正确的形状。在 for 循环中,我之前的函数中的符号是 Princ[j, i, :, :] = x[i, j]... 因此,由于稍后将数据输入和输出函数的方式,它们被交换了。但是一旦我转置了数组,它运行良好,从大约 3-4 分钟的计算时间到大约 30 秒,所以我认为这是一场胜利!也感谢您通知我跳过 xx = np.array(xx) 的转换,我认为这也节省了一些内存和时间。
  • 还将尝试使用 .value(),或者按照 pandas 文档中所述的 .to_numpy() 来查看是否也有帮助。
  • 别忘了点赞并选择点击答案旁边的复选标记
  • @RasmusSchützer。我已经修复了正确实施转置的答案
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-19
  • 1970-01-01
  • 2010-10-25
  • 2012-03-09
  • 2012-01-01
相关资源
最近更新 更多