越来越清楚的是,像starts
,stops
和等属性content
不应该是公开的——它们应该被视为内部的。它们是JaggedArray
工作的一部分,但不是任何锯齿状数据的属性(任何数组,其type
用于[0, N) -> [0, inf) -> X
某些数组长度N
和内部类型X
)。
您不想关心您的锯齿状数据是 a ChunkedArray
,并且对于许多操作,例如flatten()
and counts
,您并不关心:它们在 aChunkedArray
和 a上同样适用JaggedArray
。但是starts
, stops
, andcontent
永远不会是这样的:除了 a 的具体实现之外,它们没有任何意义JaggedArray
。
例如,考虑一下ChunkedArray
:
>>> array = awkward.ChunkedArray([awkward.fromiter([[1, 2, 3], [], [4, 5]]),
... awkward.fromiter([[100], [200, 300]])])
>>> array
<ChunkedArray [[1 2 3] [] [4 5] [100] [200 300]] at 0x796a969db6a0>
我们可以得到each的starts
and ,但这可能不是你想要的:stops
chunk
>>> [x.starts for x in array.chunks]
[array([0, 3, 3]), array([0, 1])]
>>> [x.stops for x in array.chunks]
[array([3, 3, 5]), array([1, 3])]
(在你的情况下,你有惰性数组,它们是ChunkedArray
of VirtualArray
,所以你必须做x.array.starts
而不是x.starts
, 来解包VirtualArray
。这是另一个可能应该是内部的属性,出于同样的原因。)
请注意,starts
第二个的chunk
重新开始于0
? 那是因为索引与您当前的索引相关chunk
(因此chunks
可以并行处理)。如果您将starts
其用作数据分析的一部分,那将是一个重要的修正。(您可以将stops[-1] if len(stops) > 0 else 0
前一个添加chunk
到当前chunk
以使数字全局化。)
一个可能更好的选择是从 构造有意义的偏移量counts
。有ChunkedArray
一个功能counts
:
>>> array.counts
array([3, 0, 2, 1, 2])
counts
是锯齿状数据中每个子数组的长度,它是 的导数,offsets
它是starts
和stops
重叠的:
>>> offsets = numpy.empty(len(array) + 1, dtype=int)
>>> offsets[0] = 0
>>> numpy.cumsum(array.counts, out=offsets[1:])
array([3, 3, 5, 6, 8])
>>> offsets
array([0, 3, 3, 5, 6, 8])
>>> starts, stops = offsets[:-1], offsets[1:]
>>> starts
array([0, 3, 3, 5, 6])
>>> stops
array([3, 3, 5, 6, 8])
您可以将它们用作starts
and stops
,但前提是您有某种与starts
andstops
完全连续的“内容”。不能保证 a JaggedArray
's content
,但flatten()
会为您做到这一点:
>>> content = array.flatten()
>>> content
<ChunkedArray [1 2 3 ... 100 200 300] at 0x796aa12b1940>
现在,例如,索引处的子数组3
是
>>> content[starts[3]:stops[3]]
<ChunkedArray [100] at 0x796a96a3b978>
这正是为什么 Awkward 0 ChunkedArray
、JaggedArray
等将成为Awkward 1中的内部“仅供专家使用”课程的原因。Awkward 1 中的用户界面将有一个awkward.Array
带有 a 的类type
来知道它是否是锯齿状的。无论它是由块还是其他东西组成,都将是一个实现细节。