【发布时间】:2021-01-14 18:19:28
【问题描述】:
通过切片/索引索引NumPy 数组创建了一个轻量级视图(不复制数据)并允许分配给原始数组的元素。即
import numpy as np
a = np.array([1, 2, 3, 4, 5])
a[2:4] = [6, 7]
print(a)
# [1 2 6 7 5]
但是多个视图怎么样,我如何连接它们以创建一个更大的视图,仍然分配给原始的第一个数组。例如。虚函数concatenate_views(...):
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
concatenate_views((a[1:3], a[4:6], a[7:9])) = [11, 12, 13, 14, 15, 16]
print(a)
# should print [1 11 12 4 13 14 7 15 16 10]
当然,我可以为它查看的每个视图创建一个索引列表,只需将切片转换为索引,然后连接这些索引。这样,我将获得连接视图的所有索引,并可以使用这些索引来创建组合视图。但这不是我想要的。我希望 NumPy 保留切片表示的概念,因为所有切片都可能很长,并且将这些切片转换和存储为索引效率低下。我希望 NumPy 了解所有连接视图的底层切片,以便在内部实现切片范围的简单循环。
也可以很好地概括这个问题。不仅连接视图,还允许形成任意的切片/索引操作树,例如连接视图,然后应用一些切片,然后索引,然后切片,然后再次连接。还有N维切片/索引。 IE。所有花哨的东西都可以用单个未连接的视图来完成。
级联视图的要点只是效率。当然,我们可以通过整数索引的 N 维数组(坐标,如网格网格)来表示任何视图或切片操作,然后可以使用该数组来制作源数组的视图。但是,如果 numpy 可以保留切片源集而不是整数数组的概念,那么首先它将是轻量级的(内存消耗少得多),其次不是从内存中读取索引 numpy 可以更有效地循环(迭代)每个切片在C++ 循环中。
通过连接视图,我希望能够以有效的方式将任何 numpy 操作(如 np.mean(...))应用于组合视图。
下面描述了基于 2D 示例的 N-D 切片的连接视图的完整过程:
1 Step described below:
2D array slicing using 3 slices for each axis
a,b,c - sizes of "slices" along axis 0
d,e,f - sizes of "slices" along axis 1
Each "slice" - is either slice(start, stop, step) or 1D array of integer indexes
d e f
.......
a.0.1.2.
.......
b.3.4.5.
.......
c.6.7.8.
.......
Above 0 1 2 3 4 5 6 7 8 mean not a single integer but some 2D sub-array.
Dots (`.`) also mean some 2D sub-arrays.
Sub-views shapes:
0:(a, d), 1:(a, e), 2:(a, f)
3:(b, d), 4:(b, e), 5:(b, f)
6:(c, d), 7:(c, e), 8:(c, f)
Final aggregated (concatenated) view shape:
((a + b + c), (d + e + f))
containing 2D array
012
345
678
There can be more than one Steps, each next Step applies new sequence of slicing
to the final view obtained on previous Step. Each Step has different set of sizes
of slices and different amount of slices per each dimension.
In general each next Step reduces number of total elements, except the case
when slices or indexes overlap then you may get more elements but with duplicates.
【问题讨论】:
-
那些总是等间隔的切片吗?
-
@Divakar 它可以简化原因的解决方案。但我想要一些通用功能。这允许形成任何切片树。 IE。将切片应用于切片。将索引应用于切片等。与单个未连接视图可以完成的相同花哨的东西。还有 N-D 切片。
-
然后,只需创建一个初始化为零的布尔掩码,并迭代地为这些切片分配 True。最后做
a[mask] = new_values。 -
在我上面的问题中,我提到了这种情况,说我真的希望 NumPy 保留源切片的概念,而不是转换为普通索引或布尔值,因为数组可能非常大,而且索引不仅消耗大量内存,但处理速度也很慢。如果 NumPy 保持原始切片,那么它可以在内部组织切片范围内的可能递归循环。所以切片允许在 NumPy 中使用快速和轻量级的算法。
-
掩码没有整数索引那么糟糕,与等长的 int 数组相比,布尔掩码的内存开销只有 1/8。不要在没有尝试对您的情况有效的情况下就下结论。最后,如果你有长切片,你可能想简单地迭代和分配。
标签: python arrays numpy reference slice