【问题标题】:How to avoid for-loop while using append()如何在使用 append() 时避免 for 循环
【发布时间】:2019-09-29 09:34:43
【问题描述】:

首先,我很抱歉我是 python 和 numpy 的绝对初学者。请原谅我的无知。

我有一个 4D 压力测量立方体,其维度是(样本数、时间、y 轴、x 轴),这意味着对于每个样本,我都有一个时空分布的 3D 立方体。我需要收集这个 3D 立方体的压力读数(时间、y 轴、x 轴)并将其存储到每个样本的数组中,仅在坐标满足特定条件的情况下。在改变特定条件时,该数组的大小也会发生变化。所以,我必须使用 append() 来构建这个数组。但是,由于对于 1000 个样本,我必须使用 For-Loop 为每个样本搜索超过一百万个坐标,我编写的代码效率非常低,并且需要大量时间来运行(超过几个小时)。你能帮我写得更有效率吗?

以下是我尝试解决问题的代码。它工作得很好并给出了预期的结果,但它非常慢。

import numpy as np

# Number of sample points in x,y and t-axis
Nx = 101
Ny = 101
Nt = 100
n_train = 1000
target_array = []

for i_train in range (n_train):
    for k in range (Nt):
        for j in range (Ny):
            for i in range (Nx):
                if np.round(np.sqrt((i-np.round(Nx/2))**2+(j-np.round(Ny/2))**2)) == 2*k:
                    target_array.append(Pressure[i_train,k,j,i])

【问题讨论】:

  • 它如何运作良好?您在外部循环中覆盖了 target_array,因此最后它将只包含与 i_train = 999 对应的值。
  • 非常抱歉这个错误,我从我的文件中复制代码时出错了。我已经纠正了。非常感谢您指出这一点。
  • 首先,您可以尝试在(内部)循环之外提取所有可能的(例如np.round(Nx/2))操作。这将为您带来一些时间改进,但最大因子为 10。然后您可以使用矢量化操作(np 特定)将时间减少到几秒钟(可能)。
  • 非常感谢您的建议。我为我的无知道歉,但您能否详细解释一下这句话:“那么您可以使用向量化操作(特定于 np)将时间减少到几秒钟(可能)”?
  • @CristiFati 的意思是,您应该尝试使用 numpy 数组的内置功能来执行矢量化操作,而不是依赖 Python 的 for 循环,后者的性能极差。我会尝试为您制定一个解决方案。

标签: python arrays python-3.x numpy for-loop


【解决方案1】:

由于条件涉及索引而不是 4D 数组的值,您可以使用 numpy.meshgrid 对其进行矢量化。

这里 pp 是你的 4D 数组:

iv, jv, kv = np.meshgrid(np.arange(pp.shape[3]), np.arange(pp.shape[2]), np.arange(pp.shape[1]))
selecting = np.round(np.sqrt((iv - np.round(pp.shape[3]/2))**2 + (jv - np.round(pp.shape[2]/2))**2)) == 2*kv
target = pp[:,selecting]

如果我正确理解了您的 4D 数组的组织方式:

  • meshgrid 创建的数组保存索引以选择在 3 个维度 x、y、t 上的 pp 元素。
  • selecting 是通过复制您的方程式创建的布尔数组,用于检查哪些坐标满足条件。
  • targetpp 的选择,取 0 轴上满足其他 3 个轴上的条件(即selecting 为 True)的所有元素。

注意target 是一个二维数组,要拥有一个一维数组,请使用target.flatten()

【讨论】:

    猜你喜欢
    • 2023-03-27
    • 1970-01-01
    • 1970-01-01
    • 2021-06-08
    • 1970-01-01
    • 1970-01-01
    • 2018-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多