越来越清楚的是,像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的startsand ,但这可能不是你想要的:stopschunk
>>> [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])]
(在你的情况下,你有惰性数组,它们是ChunkedArrayof 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])
您可以将它们用作startsand stops,但前提是您有某种与startsandstops完全连续的“内容”。不能保证 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来知道它是否是锯齿状的。无论它是由块还是其他东西组成,都将是一个实现细节。