【发布时间】:2018-08-06 10:51:08
【问题描述】:
假设我有一个 NumPy 数组:
>>> X = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
>>> X
array([[ 1, 2, 3, 4],
[ 5, 6, 7, 8],
[ 9, 10, 11, 12]])
以及我要为每一行选择的索引数组:
>>> ixs = np.array([[1, 3], [0, 1], [1, 2]])
>>> ixs
array([[1, 3],
[0, 1],
[1, 2]])
如何索引数组 X 以便为 X 中的每一行选择 ixs 中指定的两个索引?
所以对于这种情况,我想为第一行选择元素 1 和 3,为第二行选择元素 0 和 1,依此类推。输出应该是:
array([[2, 4],
[5, 6],
[10, 11]])
一个缓慢的解决方案是这样的:
output = np.array([row[ix] for row, ix in zip(X, ixs)])
但是,对于极长的数组,这可能会有点慢。有没有使用 NumPy 没有循环的更快方法?
编辑:在 2.5K * 1M 阵列和 2K 宽 ixs (10GB) 上进行一些非常近似的速度测试:
np.array([row[ix] for row, ix in zip(X, ixs)])0.16s
X[np.arange(len(ixs)), ixs.T].T0.175s
X.take(idx+np.arange(0, X.shape[0]*X.shape[1], X.shape[1])[:,None])33s
np.fromiter((X[i, j] for i, row in enumerate(ixs) for j in row), dtype=X.dtype).reshape(ixs.shape)2.4s
【问题讨论】:
-
这会产生一个接近你想要的数组:
X[:,ixs]。任何人都可以在此基础上进行构建吗? -
您认为并行化是一种可接受的解决方案吗?
-
你能像这样重建 ixs:
ixs2 = np.array(((0, 1), (0, 3), (1, 0), ...))?如果是这样,那么X[ixs2[:,0], ixs2[:,1]]会得到我认为你需要的东西。 -
否 @MohsinBukhari 我已经在更高的循环上并行化。我也不认为并行化在这里会有所帮助,因为在进程之间传递信息很慢。
-
嗯,您是否尝试过使用
numbaJIT 的直接 for 循环实现?
标签: python arrays numpy optimization indexing