表示连接切片的切片

Tri*_*ion 5 python numpy slice

切片的索引slice(start, stop[, step])通常可以表示为range(start, stop, step)(或者range(*slice(start, stop, step).indices(length))在考虑基础维度时).

假设我有两个多维切片,第二个切片可以用作应用第一个切片的结果的切片.

例:

import numpy as np
data = np.random.rand(*(100, 100, 100))
a = data[::2, 7, :] # slice 1, a.shape = (50,100)
b = a[1, ::-1] # slice 2, b.shape = (100,)
Run Code Online (Sandbox Code Playgroud)

我想找到一个用于计算执行相同工作的单个切片的通用表达式.我知道底层数据结构的维度.

c = data[2, 7, ::-1] # same as b
np.array_equal(b, c) # True
Run Code Online (Sandbox Code Playgroud)

所以,从获得[::2, 7, :][1, ::-1][2, 7, ::-1] 在这个例子中,我需要像一个函数:

def concatenate_slices(shape, outer_slice, inner_slice):
    ...
    return combined_slice
Run Code Online (Sandbox Code Playgroud)

哪里outer_sliceinner_slice都将成为切片的元组.在示例shape=(100, 100, 100)outer_slice=(slice(None, None, 2), 7, slice(None, None, None))inner_slice=(1, slice(None, None, -1)).

我不确定如何有效地做到这一点.

__getitem__(slice)调用时我的对象做了一些事情(没有中间视图),我想只做一次,但仍然有可能有片切片.

作为扩展(可选)我想知道如果切片中有椭圆会发生什么.我怎样才能组合起来呢?

per*_*iae 1

让我们从简单的情况开始:一维数组。我们需要跟踪最终切片的startstop和值,我们可以像这样更新:step

def update_1d(a, b, length):
  a_start, a_stop, a_step = a.indices(length)
  a_length = len(xrange(a_start, a_stop, a_step))
  if a_length == 0:
    # doesn't matter what b is if data[a] is []
    return a
  b_start, b_stop, b_step = b.indices(a_length)
  b_length = len(xrange(b_start, b_stop, b_step))
  if b_length == 0:
    # result will be empty, so we can exit early
    return slice(0, 0, 1)
  # convert b's start into a's coordinates, without wrapping around
  start = max(0, a_start + b_start * a_step)
  # steps are multiplicative, which makes things easy
  step = a_step * b_step
  # the stop index is the hard part because it depends on the sign of both steps
  x = a_start + b_stop * a_step
  if step < 0:
    # indexing backwards, so truncate if b's converted step goes below zero
    stop = x if x >= 0 else None
  elif a_step > 0:
    # both steps are positive, so take the smallest stop index
    stop = min(a_stop, x)
  else:
    # both steps are negative, so take the largest stop index
    stop = max(a_stop, x)
  return slice(start, stop, step)
Run Code Online (Sandbox Code Playgroud)

请注意,这期望a并且b是切片。不过,您通常可以将其他形式转换为切片对象。这甚至包括Ellipsis物体,假设你知道你有多少个维度。

为了将其扩展到多维情况,我们需要做一些簿记来跟踪哪个原始维度被切片。例如,如果有data[::2, 7, :][:, 2:-2],则必须将第二个切片的第二个维度映射到第一个切片的第三个维度。