如果我有一个像对象定义的切片对象:s = np.s_[10:20, 30:40]
,有没有简单的方法对这个对象进行基本的操作/操作,而不必手动访问s[0][0]
等...创建新切片?
示例:是否有一个神奇的功能可以将切片移动(x,y)
以获得shifted(s, x, y) = np.s_[10+x:20+x, 30+y:40+y]
,或者我是否必须创建自己的函数来执行所有这些基本操作?
答案 0 :(得分:3)
In [319]: s=np.s_[10:20, 30:40]
In [320]: s
Out[320]: (slice(10, 20, None), slice(30, 40, None))
因此结果是一个包含2个slice
个对象的元组。
In [322]: s[0].start
Out[322]: 10
In [324]: s[0].start=20
...
AttributeError: readonly attribute
因此可以创建slice
,但不能更改属性。但这没什么大不了的。创建切片并不昂贵。它不是一个大数组或列表。它只是一个具有几个属性的简单对象。
要将其展开为数组,请使用np.r_
:
In [325]: np.r_[s]
Out[325]:
array([10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39])
或者s
元组可用于索引数组:
In [328]: arr = np.arange(30*50).reshape(30,50)
In [329]: arr[s]
Out[329]:
array([[530, 531, 532, 533, 534, 535, 536, 537, 538, 539],
[580, 581, 582, 583, 584, 585, 586, 587, 588, 589],
[630, 631, 632, 633, 634, 635, 636, 637, 638, 639],
[680, 681, 682, 683, 684, 685, 686, 687, 688, 689],
[730, 731, 732, 733, 734, 735, 736, 737, 738, 739],
[780, 781, 782, 783, 784, 785, 786, 787, 788, 789],
[830, 831, 832, 833, 834, 835, 836, 837, 838, 839],
[880, 881, 882, 883, 884, 885, 886, 887, 888, 889],
[930, 931, 932, 933, 934, 935, 936, 937, 938, 939],
[980, 981, 982, 983, 984, 985, 986, 987, 988, 989]])
与arr[10:20, 30:40]
相同,是arr
的视图。您无法修改视图(范围),但您当然可以使用新切片创建新视图。
来自np.s_
np.lib.index_tricks.py
代码
class IndexExpression(object):
"""
A nicer way to build up index tuples for arrays.
...
"""
def __init__(self, maketuple):
self.maketuple = maketuple
def __getitem__(self, item):
if self.maketuple and not isinstance(item, tuple):
return (item,)
else:
return item
index_exp = IndexExpression(maketuple=True)
s_ = IndexExpression(maketuple=False)
基本上它只是捕获Python解释器在看到x[0:3, :]
之类的代码时生成的元组的一种方式。它会将其转换为x.__getitem__(atuple)
。
In [334]: np.s_[:,3:3,[1,2,3]]
Out[334]: (slice(None, None, None), slice(3, 3, None), [1, 2, 3])
逗号分隔元组元素,n:m:i
字符串转换为slice
个对象。这个纯Python; numpy
没什么特别的。除了大多数标准的Python类列表都不能使用元组索引。
In [336]: list(range(10))[np.s_[2:5]]
Out[336]: [2, 3, 4]
在同一个index_tricks
文件中,查看类AxisConcatenator
和nd_grid
,以便对key
的{{1}}参数进行更复杂的处理。
答案 1 :(得分:1)
python slice
对象没有关联的方法,而numpy
似乎只是在不修改的情况下重用该类(尽管有一个新的构造函数s_
)。所以,似乎答案是肯定的。
如果你真的想要使用切片,你需要编写自己的函数:
def shifted(s, x, y):
return np.s_[s[0].start + x: s[0].stop + x, s[1].start + y: s[1].stop + y]
然后你可以重新分配:
s = shifted(s, x, y)
或者您可以创建slice
的子类并将其实现为该类的方法。
答案 2 :(得分:0)
您可以只使用坐标网格来代替使用切片:
s = tuple(np.mgrid[10:20, 30:40])
s
可以像slice
一样被调用,但像array
一样被操纵
arr[s] # using hpaulj's test data
Out[]:
array([[530, 531, 532, 533, 534, 535, 536, 537, 538, 539],
[580, 581, 582, 583, 584, 585, 586, 587, 588, 589],
[630, 631, 632, 633, 634, 635, 636, 637, 638, 639],
[680, 681, 682, 683, 684, 685, 686, 687, 688, 689],
[730, 731, 732, 733, 734, 735, 736, 737, 738, 739],
[780, 781, 782, 783, 784, 785, 786, 787, 788, 789],
[830, 831, 832, 833, 834, 835, 836, 837, 838, 839],
[880, 881, 882, 883, 884, 885, 886, 887, 888, 889],
[930, 931, 932, 933, 934, 935, 936, 937, 938, 939],
[980, 981, 982, 983, 984, 985, 986, 987, 988, 989]])
def shifted(s, x, y):
return (s[0] + x, s[1] + y)
arr[shifted(s,10,10)]
Out[]:
array([[1040, 1041, 1042, 1043, 1044, 1045, 1046, 1047, 1048, 1049],
[1090, 1091, 1092, 1093, 1094, 1095, 1096, 1097, 1098, 1099],
[1140, 1141, 1142, 1143, 1144, 1145, 1146, 1147, 1148, 1149],
[1190, 1191, 1192, 1193, 1194, 1195, 1196, 1197, 1198, 1199],
[1240, 1241, 1242, 1243, 1244, 1245, 1246, 1247, 1248, 1249],
[1290, 1291, 1292, 1293, 1294, 1295, 1296, 1297, 1298, 1299],
[1340, 1341, 1342, 1343, 1344, 1345, 1346, 1347, 1348, 1349],
[1390, 1391, 1392, 1393, 1394, 1395, 1396, 1397, 1398, 1399],
[1440, 1441, 1442, 1443, 1444, 1445, 1446, 1447, 1448, 1449],
[1490, 1491, 1492, 1493, 1494, 1495, 1496, 1497, 1498, 1499]])
请注意,这会比切片占用更多内存