python - 使用多个切片对象反转 2D NumPy 数组

标签 python numpy

问题

我有一个 2D NumPy 数组 arr,对于每一行,我想反转数组的一部分。至关重要的是,对于每一行,startstop 索引必须是唯一的。我可以使用以下方法来实现这一点。

import numpy as np

arr = np.repeat(np.arange(10)[np.newaxis, :], 3, axis=0)
reverse = np.sort(np.random.choice(arr.shape[1], [arr.shape[0], 2], False))

# arr
# array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
#        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
#        [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])

# reverse
# array([[1, 7],
#        [8, 9],
#        [4, 6]])

反转 `reverse 中 startstop 索引之间的每一行。

for idx, (i, j) in enumerate(reverse):
    arr[idx, i:j+1] = arr[idx, i:j+1][::-1]

# arr 
# array([[0, 7, 6, 5, 4, 3, 2, 1, 8, 9],
#        [0, 1, 2, 3, 4, 5, 6, 7, 9, 8],
#        [0, 1, 2, 3, 6, 5, 4, 7, 8, 9]])
<小时/>

问题

使用基本的切片和索引可以实现这一点吗?我尝试使用reverse的输出来形成多个slice对象,但没有成功。

<小时/>

更新

原始方法与答案的简单比较。对于我的数据,该解决方案只需要处理形状为 (50, 100) 的二维矩阵。

import numpy as np

def reverse_one(arr, n): 
    temp = np.repeat(arr.copy(), n, axis=0)
    reverse = np.sort(np.random.choice(temp.shape[1], [n, 2], False))

    for idx, (i, j) in enumerate(reverse):
        temp[idx, i:j+1] = temp[idx, i:j+1][::-1]

    return temp

def reverse_two(arr, n):
    temp = np.repeat(arr.copy(), n, axis=0)
    reverse = np.sort(np.random.choice(temp.shape[1], [n, 2], False))
    rev = np.ravel_multi_index((np.arange(n)[:, np.newaxis], reverse), temp.shape)
    rev[:, 1] += 1
    idx = np.arange(temp.size).reshape(temp.shape)
    s = np.searchsorted(rev.ravel(), idx, 'right')
    m = (s % 2 == 1)
    g = rev[s[m] // 2]
    idx[m] = g[:, 0] - (idx[m] - g[:, 1]) - 1

    return temp.take(idx)

m = 100
arr = np.arange(m)[np.newaxis, :]

print("reverse_one:")
%timeit reverse_one(arr, m//2)
print("=" * 40)
print("reverse_two:")
%timeit reverse_two(arr, m//2)

在 Jupyter Notebook 中运行以下代码会得到以下结果。

reverse_one:
1000 loops, best of 5: 202 µs per loop
========================================
reverse_two:
1000 loops, best of 5: 363 µs per loop

最佳答案

这有点棘手,但我找到了一种方法。不过,高级索引的成本很高,因此您必须根据您拥有的数据来确定它是否真的更快。

import numpy as np

np.random.seed(0)
arr = np.repeat(np.arange(10)[np.newaxis, :], 3, axis=0)
reverse = np.sort(np.random.choice(arr.shape[1], [arr.shape[0], 2], False))
print(arr)
# [[0 1 2 3 4 5 6 7 8 9]
#  [0 1 2 3 4 5 6 7 8 9]
#  [0 1 2 3 4 5 6 7 8 9]]
print(reverse)
# [[2 8]
#  [4 9]
#  [1 6]]

# Get "flat" indices of the bounds
rev = np.ravel_multi_index((np.arange(arr.shape[0])[:, np.newaxis], reverse), arr.shape)
# Add one to the second bound (so it is first index after the slice)
rev[:, 1] += 1
# Make array of flat indices for the data
idx = np.arange(arr.size).reshape(arr.shape)
# Find the position of flat indices with respect to bounds
s = np.searchsorted(rev.ravel(), idx, 'right')
# For each "i" within a slice, "s[i]" is odd
m = (s % 2 == 1)
# Replace indices within slices with their reversed ones
g = rev[s[m] // 2]
idx[m] = g[:, 0] - (idx[m] - g[:, 1]) - 1
# Apply indices to array
res = arr.take(idx)
print(res)
# [[0 1 8 7 6 5 4 3 2 9]
#  [0 1 2 3 9 8 7 6 5 4]
#  [0 6 5 4 3 2 1 7 8 9]]

关于python - 使用多个切片对象反转 2D NumPy 数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59951813/

相关文章:

python - 如何将文件中不同类型的数据导入 Python Numpy 数组?

python - PyInstaller: IOError: [Errno 2] 没有这样的文件或目录:

python - 如何在txt文件中查找字符串

python - 如何获得该数据集的正确输出?

python - 从 tf.data 中仅提取 numpy 数组的一部分

python - 在 numpy 中计算累积乘积或总和时提前中断

python - 仅从数据框中获取前三个值

Python urllib2.urlopen() 很慢,需要一个更好的方法来读取多个 url

Python 包构建 - 导入函数以在类定义中使用

python - 如何对列表列表进行排序并仅保留每个第一个元素的最大第二个元素?