我有一些适合JaggedArrays提取contentstartsstops的代码,但是我想在某些ChunkedArrays上运行相同的代码,这些lazyarrays是从uproot的获取的。
不幸的是,我得到了以下错误:

~/.local/lib/python3.7/site-packages/awkward/array/base.py in __getattr__(self, where)
    254                     raise AttributeError("while trying to get column {0}, an exception occurred:\n{1}: {2}".format(repr(where), type(err), str(err)))
    255             else:
--> 256                 raise AttributeError("no column named {0}".format(repr(where)))
    257
    258     def __dir__(self):

AttributeError: no column named 'starts'


有什么办法可以使它起作用?

最佳答案

逐渐变得清楚的是,诸如startsstopscontent之类的属性不应公开,它们应被视为内部属性。它们是使JaggedArray工作的一部分,但不是任何锯齿数据的属性(对于某些数组长度type和内部类型[0, N) -> [0, inf) -> X,其NX的任何数组)。

您不希望您的锯齿数据是ChunkedArray,并且对于许多操作(例如flatten()counts),您都不在乎:它们在ChunkedArray上与JaggedArray同样有效。但是startsstopscontent永远不会像这样:除了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>


我们可以得到每个startsstopschunk,但这可能不是您想要的:

>>> [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])]


(在您的情况下,您有惰性数组,它们是ChunkedArrayVirtualArray,因此您必须执行x.array.starts而不是x.starts来解包VirtualArray。这可能是另一个属性出于相同的原因)。

注意第二个startschunk0重新开始吗?这是因为索引是相对于您当前的chunk的(因此chunks可以并行处理)。如果将starts用作数据分析的一部分,那将是一个重要的更正。 (您可以将前一个stops[-1] if len(stops) > 0 else 0chunk添加到当前的chunk中,以使数字具有全局性。)

也许更好的选择是从counts构造有意义的偏移量。 ChunkedArray具有正常运行的counts

>>> array.counts
array([3, 0, 2, 1, 2])


counts是锯齿状数据中每个子数组的长度,是offsets的派生形式,startsstops重叠:

>>> 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])


您可以将它们用作startsstops,但前提是您有某种且它们与startsstops完全相邻。不能保证JaggedArraycontent,但是flatten()会为您做到这一点:

>>> content = array.flatten()
>>> content
<ChunkedArray [1 2 3 ... 100 200 300] at 0x796aa12b1940>


现在,例如,索引为3的子数组为

>>> content[starts[3]:stops[3]]
<ChunkedArray [100] at 0x796a96a3b978>


这就是为什么尴尬的0的ChunkedArrayJaggedArray等将成为内部的“仅面向专家”类的原因。尴尬1中的用户界面将只有一个awkward.Array类和一个type来了解其是否呈锯齿状。无论是用块还是其他东西制成,都将是实现细节。

10-08 16:27