gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 06:30:07 25 4
gpt4 key购买 nike

问题

我有一个 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com