有没有一种方法可以有条件地将多维NumPy数组的内容复制到另一个数组?

ikfrs5lh  于 2023-10-19  发布在  其他
关注(0)|答案(2)|浏览(93)

我在numpy中有一个任意长度的2D数组,其中每个内部列表(记录)包含10个元素。有没有一种方法可以遍历整个2D数组,并根据条件创建一个只包含通过测试的记录的新数组?
类似于下面的伪代码:

array1 = np.array([1.142,2,3.10042,4,5,6,7.34141,8,9,10],[2.1535,3,4,5,6.000212,7,8,9,10,11],...)
array2 = np.empty(np.shape(array1)

for x in range(len(array1)):
    if array1[x][3] > 15:
        array2 = array1[x]
    else:
        continue
mjqavswn

mjqavswn1#

使用布尔索引:

array2 = np.zeros(np.shape(array1))

m = array1[:, 3]>15

array2[m] = array1[m]

还要注意,必须用numpy.zeros初始化array1,否则所有未赋值的值将具有任意数字。

oxf4rvwz

oxf4rvwz2#

你可以使用numpy.where来选择array1中满足你的条件的元素:

array2 = np.where(array1[:, 3, None] > 15, array1, 0)

这将查找array1的第三列大于15的行,并从array1中选择其他所有地方都为零的行。
请注意,[:, 3, None]索引用于防止维度的自动压缩,以创建一个 * 列向量 *,该向量可以广播到原始数组以选择整行。使用array1[:, 3] > 15将导致
ValueError:操作数无法与形状(20,)(20,10)()一起广播
mozway's answer相比,where方法在我的计算机上快了约2倍:

import numpy as np
import timeit
def make_inputs(size):
    a = np.random.random((size, size))
    c = np.random.randint(size)
    v = np.random.random()
    return a, c, v

def f1(arr, col, val):
    array2 = np.zeros_like(arr)
    m = arr[:, col] > val
    array2[m] = arr[m]
    return array2

def f2(arr, col, val):
    return np.where(arr[:, col, None] > val, arr, 0)

sizes = [10, 100, 1000, 5000, 10_000, 50_000]
times = np.zeros((len(sizes), 2))

for i, s in enumerate(sizes):
    a, c, v = make_inputs(s)
    assert (f1(a, c, v) == f2(a, c, v)).all(), "Different outputs from both functions"
    times[i, 0] = timeit.timeit('f1(a, c, v)', globals=globals, number=10)
    times[i, 0] = timeit.timeit('f2(a, c, v)', globals=globals, number=10)

在我的计算机上,这给出了下面的times,它显示了np.where(在下面的图中标记为f2)相对于布尔索引方法(标记为f1)的一致约2倍的加速:

array([[9.20000020e-05, 4.53998800e-05],
       [1.47900078e-04, 9.87001695e-05],
       [4.83841999e-02, 1.88557999e-02],
       [1.02645030e+00, 5.64855800e-01],
       [4.05608600e+00, 2.33924000e+00],
       [8.85297001e+01, 5.98397732e+01]])

相关问题