Numpy:您可以使用广播按行替换值吗?
Numpy: Can you use broadcasting to replace values by row?
我有一个 M x N 矩阵 X 和一个 1 x N 矩阵 Y。我想做的是根据其列用 Y 中的适当值替换 X 中的任何 0 项。
所以如果
X = np.array([[0, 1, 2], [3, 0, 5]])
和
Y = np.array([10, 20, 30])
期望的最终结果将是 [[10, 1, 2], [3, 20, 5]]。
这可以通过生成一个 M x N 矩阵(其中每一行都是 Y)然后使用过滤器数组来直接完成:
Y = np.ones((X.shape[0], 1)) * Y.reshape(1, -1)
X[X==0] = Y[X==0]
但这可以使用 numpy 的广播功能来完成吗?
当然可以。使用 numpy.broadcast_to
:
创建形状为 X
的 Y
的广播视图,而不是物理重复 Y
expanded = numpy.broadcast_to(Y, X.shape)
mask = X==0
x[mask] = expanded[mask]
扩展 X
使其更通用:
In [306]: X = np.array([[0, 1, 2], [3, 0, 5],[0,1,0]])
where
标识0;第二个数组标识列
In [307]: idx = np.where(X==0)
In [308]: idx
Out[308]: (array([0, 1, 2, 2]), array([0, 1, 0, 2]))
In [309]: Z = X.copy()
In [310]: Z[idx]
Out[310]: array([0, 0, 0, 0]) # flat list of where to put the values
In [311]: Y[idx[1]]
Out[311]: array([10, 20, 10, 30]) # matching list of values by column
In [312]: Z[idx] = Y[idx[1]]
In [313]: Z
Out[313]:
array([[10, 1, 2],
[ 3, 20, 5],
[10, 1, 30]])
不做广播,但还算干净numpy
。
与broadcast_to
方法相比的时间
In [314]: %%timeit
...: idx = np.where(X==0)
...: Z[idx] = Y[idx[1]]
...:
9.28 µs ± 157 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [315]: %%timeit
...: exp = np.broadcast_to(Y,X.shape)
...: mask=X==0
...: Z[mask] = exp[mask]
...:
19.5 µs ± 513 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
更快,尽管样本量很小。
另一种实现 expanded
Y
的方法是使用 repeat
:
In [319]: %%timeit
...: exp = np.repeat(Y[None,:],3,0)
...: mask=X==0
...: Z[mask] = exp[mask]
...:
10.8 µs ± 55.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
谁的时间接近我的where
。结果发现broadcast_to
比较慢:
In [321]: %%timeit
...: exp = np.broadcast_to(Y,X.shape)
...:
10.5 µs ± 52.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [322]: %%timeit
...: exp = np.repeat(Y[None,:],3,0)
...:
3.76 µs ± 11.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
我们必须做更多的测试,看看这是否只是由于设置成本,或者相对时间是否仍然适用于更大的阵列。
我有一个 M x N 矩阵 X 和一个 1 x N 矩阵 Y。我想做的是根据其列用 Y 中的适当值替换 X 中的任何 0 项。
所以如果
X = np.array([[0, 1, 2], [3, 0, 5]])
和
Y = np.array([10, 20, 30])
期望的最终结果将是 [[10, 1, 2], [3, 20, 5]]。
这可以通过生成一个 M x N 矩阵(其中每一行都是 Y)然后使用过滤器数组来直接完成:
Y = np.ones((X.shape[0], 1)) * Y.reshape(1, -1)
X[X==0] = Y[X==0]
但这可以使用 numpy 的广播功能来完成吗?
当然可以。使用 numpy.broadcast_to
:
X
的 Y
的广播视图,而不是物理重复 Y
expanded = numpy.broadcast_to(Y, X.shape)
mask = X==0
x[mask] = expanded[mask]
扩展 X
使其更通用:
In [306]: X = np.array([[0, 1, 2], [3, 0, 5],[0,1,0]])
where
标识0;第二个数组标识列
In [307]: idx = np.where(X==0)
In [308]: idx
Out[308]: (array([0, 1, 2, 2]), array([0, 1, 0, 2]))
In [309]: Z = X.copy()
In [310]: Z[idx]
Out[310]: array([0, 0, 0, 0]) # flat list of where to put the values
In [311]: Y[idx[1]]
Out[311]: array([10, 20, 10, 30]) # matching list of values by column
In [312]: Z[idx] = Y[idx[1]]
In [313]: Z
Out[313]:
array([[10, 1, 2],
[ 3, 20, 5],
[10, 1, 30]])
不做广播,但还算干净numpy
。
与broadcast_to
方法相比的时间
In [314]: %%timeit
...: idx = np.where(X==0)
...: Z[idx] = Y[idx[1]]
...:
9.28 µs ± 157 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [315]: %%timeit
...: exp = np.broadcast_to(Y,X.shape)
...: mask=X==0
...: Z[mask] = exp[mask]
...:
19.5 µs ± 513 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
更快,尽管样本量很小。
另一种实现 expanded
Y
的方法是使用 repeat
:
In [319]: %%timeit
...: exp = np.repeat(Y[None,:],3,0)
...: mask=X==0
...: Z[mask] = exp[mask]
...:
10.8 µs ± 55.3 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
谁的时间接近我的where
。结果发现broadcast_to
比较慢:
In [321]: %%timeit
...: exp = np.broadcast_to(Y,X.shape)
...:
10.5 µs ± 52.9 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
In [322]: %%timeit
...: exp = np.repeat(Y[None,:],3,0)
...:
3.76 µs ± 11.6 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
我们必须做更多的测试,看看这是否只是由于设置成本,或者相对时间是否仍然适用于更大的阵列。