我有一棵树,其中一个分支存储一个字符串。当我读取使用uproot.open()方法时,arrays()我得到以下内容:
uproot.open()
arrays()
>>> array_train['backtracked_end_process'] <ObjectArray [b'FastScintillation' b'FastScintillation' b'FastScintillation' ... b'FastScintillation' b'FastScintillation' b'FastScintillation'] at 0x7f48936e6c90>
我想使用这个分支来创建面具,通过做类似的事情 array_train['backtracked_end_process'] != b'FastScintillation' ,但不幸的是这会产生一个错误:
array_train['backtracked_end_process'] != b'FastScintillation'
--------------------------------------------------------------------------- ValueError Traceback (most recent call last) <ipython-input-97-a28f3706c5b5> in <module> ----> 1 array_train['backtracked_end_process'] == b'FastScintillation' ~/.local/lib/python3.7/site-packages/numpy/lib/mixins.py in func(self, other) 23 if _disables_array_ufunc(other): 24 return NotImplemented ---> 25 return ufunc(self, other) 26 func.__name__ = '__{}__'.format(name) 27 return func ~/.local/lib/python3.7/site-packages/awkward/array/objects.py in __array_ufunc__(self, ufunc, method, *inputs, **kwargs) 216 contents.append(x) 217 --> 218 result = getattr(ufunc, method)(*contents, **kwargs) 219 220 if self._util_iscomparison(ufunc): ~/.local/lib/python3.7/site-packages/awkward/array/jagged.py in __array_ufunc__(self, ufunc, method, *inputs, **kwargs) 987 data = self._util_toarray(inputs[i], inputs[i].dtype) 988 if starts.shape != data.shape: --> 989 raise ValueError("cannot broadcast JaggedArray of shape {0} with array of shape {1}".format(starts.shape, data.shape)) 990 991 if parents is None: ValueError: cannot broadcast JaggedArray of shape (24035,) with array of shape ()
有人对下一步有什么建议吗?如果能将其转换为,numpy.chararray问题就解决了,但我不知道该怎么做。
numpy.chararray
字符串处理是 uproot 的一个弱点。它使用自定义ObjectArray(甚至不是StringArrayweird-array 中的),bytes按需生成对象。你想要的是一个带有==重载的字符串数组类,意思是“比较每个可变长度的字符串,必要时将单个字符串广播到数组”。不幸的是,uprootObjectArray和StringArrayweird-array 中的类都还没有做到这一点。
ObjectArray
StringArray
bytes
==
因此,您可以这样做,当然是通过隐式 Python for 循环。
>>> import uproot, numpy >>> f = uproot.open("http://scikit-hep.org/uproot/examples/sample-6.10.05-zlib.root") >>> t = f["sample"] >>> t["str"].array() <ObjectArray [b'hey-0' b'hey-1' b'hey-2' ... b'hey-27' b'hey-28' b'hey-29'] at 0x7fe835b54588> >>> numpy.array(list(t["str"].array())) array([b'hey-0', b'hey-1', b'hey-2', b'hey-3', b'hey-4', b'hey-5', b'hey-6', b'hey-7', b'hey-8', b'hey-9', b'hey-10', b'hey-11', b'hey-12', b'hey-13', b'hey-14', b'hey-15', b'hey-16', b'hey-17', b'hey-18', b'hey-19', b'hey-20', b'hey-21', b'hey-22', b'hey-23', b'hey-24', b'hey-25', b'hey-26', b'hey-27', b'hey-28', b'hey-29'], dtype='|S6') >>> numpy.array(list(t["str"].array())) == b"hey-0" array([ True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False])
循环隐含在list构造函数中,该构造函数对 进行迭代ObjectArray,将每个元素转换为bytes字符串。此 Python 列表不适合一次一个数组的操作,因此我们随后构造一个 NumPy 数组,它是(以填充为代价)。
list
替代方案,可能更好:
在写这篇文章的时候,我记得 uprootObjectArray是使用一个很尴尬的 实现的JaggedArray,所以上面的转换可以用JaggedArray的regular方法来实现,这可能要快得多(没有中间的 Pythonbytes对象,没有 Python for 循环)。
JaggedArray
regular
>>> t["str"].array().regular() array([b'hey-0', b'hey-1', b'hey-2', b'hey-3', b'hey-4', b'hey-5', b'hey-6', b'hey-7', b'hey-8', b'hey-9', b'hey-10', b'hey-11', b'hey-12', b'hey-13', b'hey-14', b'hey-15', b'hey-16', b'hey-17', b'hey-18', b'hey-19', b'hey-20', b'hey-21', b'hey-22', b'hey-23', b'hey-24', b'hey-25', b'hey-26', b'hey-27', b'hey-28', b'hey-29'], dtype=object) >>> t["str"].array().regular() == b"hey-0" array([ True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False])
(上面描述的功能不是故意创建的,但它有效是因为正确的部分以偶然的方式组合在一起。)