本文介绍了多维切片的紧凑表示法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
比方说,我有3个(或更多)维数组A
和两个具有最小和最大边left
,right
的数组以对其进行切片.
Let's say I have 3 (or more) dimensional array A
and two arrays with minimum and maximum edges left
, right
for slicing it.
是否有比这更紧凑的符号来选择由我的边缘界定的视图?
Is there a more compact notation than this to select the view delimited by my edges?
V = A[left[0]:right[0], left[1]:right[1], left[2]:right[2])
也许这样的东西已经更好了
Probably something like this is already better
view = [ slice(a, b) for a,b in zip(left, right) ]
V = A[view]
但是我觉得还有一种 numpythonic 的方式,我没看到...不知道,有些是np.s_
吗?
but I feel there's a more numpythonic way I'm not seeing... don't know, something with np.s_
?
预期结果的示例
A = np.arange(1000).reshape(10,10,10)
left = np.array([0, 0, 0])
right = np.array([2, 4, 3])
view = [ slice(a, b) for a,b in zip(left, right) ]
In [32]: A[view]
Out[32]:
array([[[ 0, 1, 2],
[ 10, 11, 12],
[ 20, 21, 22],
[ 30, 31, 32]],
[[100, 101, 102],
[110, 111, 112],
[120, 121, 122],
[130, 131, 132]]])
推荐答案
您可以将np.s_
子类化以支持矢量化"切片符号:
You could subclass np.s_
to support "vectorized" slice notation:
import numpy as np
import types
class Block_Slice(np.lib.index_tricks.IndexExpression):
@staticmethod
def expand_slice(slice_, result_type=types.GeneratorType, force_type=False):
bc = np.broadcast(slice_.start, slice_.stop, slice_.step)
if bc.size == 1 and not force_type:
return slice_
if result_type in ('generator', types.GeneratorType):
return (slice(*idx) for idx in bc)
result_type = tuple if result_type=='tuple' else result_type
return result_type(slice(*idx) for idx in bc)
def __getitem__(self, item):
if isinstance(item, slice):
item = self.expand_slice(item, tuple)
elif isinstance(item, tuple):
item = tuple(j for i in item for j in
(self.expand_slice(i, force_type=True)
if isinstance(i, slice) else (i,)))
return super().__getitem__(item)
bs_ = Block_Slice(maketuple=False)
a = sum(np.ogrid[:2000:1000, :300:100, :40:10, :6])
left = [1, 0, 0]
right = [2, 2, 4]
a[bs_[left:right]]
# array([[[[1000, 1001, 1002, 1003, 1004, 1005],
# [1010, 1011, 1012, 1013, 1014, 1015],
# [1020, 1021, 1022, 1023, 1024, 1025],
# [1030, 1031, 1032, 1033, 1034, 1035]],
# [[1100, 1101, 1102, 1103, 1104, 1105],
# [1110, 1111, 1112, 1113, 1114, 1115],
# [1120, 1121, 1122, 1123, 1124, 1125],
# [1130, 1131, 1132, 1133, 1134, 1135]]]])
a[bs_[..., range(3):5]]
# array([[[[ 12, 13, 14],
# [ 22, 23, 24],
# [ 32, 33, 34]],
# [[ 112, 113, 114],
# [ 122, 123, 124],
# [ 132, 133, 134]],
# [[ 212, 213, 214],
# [ 222, 223, 224],
# [ 232, 233, 234]]],
# [[[1012, 1013, 1014],
# [1022, 1023, 1024],
# [1032, 1033, 1034]],
# [[1112, 1113, 1114],
# [1122, 1123, 1124],
# [1132, 1133, 1134]],
# [[1212, 1213, 1214],
# [1222, 1223, 1224],
# [1232, 1233, 1234]]]])
a[bs_[:right, [4, 2, 1]]]
# array([[[[ 4, 2, 1],
# [ 14, 12, 11],
# [ 24, 22, 21],
# [ 34, 32, 31]],
# [[ 104, 102, 101],
# [ 114, 112, 111],
# [ 124, 122, 121],
# [ 134, 132, 131]]],
# [[[1004, 1002, 1001],
# [1014, 1012, 1011],
# [1024, 1022, 1021],
# [1034, 1032, 1031]],
# [[1104, 1102, 1101],
# [1114, 1112, 1111],
# [1124, 1122, 1121],
# [1134, 1132, 1131]]]])
这篇关于多维切片的紧凑表示法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!