小能豆

来自 uproot 的字符串数组

py

我有一棵树,其中一个分支存储一个字符串。当我读取使用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' ,但不幸的是这会产生一个错误:

---------------------------------------------------------------------------
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问题就解决了,但我不知道该怎么做。


阅读 25

收藏
2024-12-24

共1个答案

小能豆

字符串处理是 uproot 的一个弱点。它使用自定义ObjectArray(甚至不是StringArrayweird-array 中的),bytes按需生成对象。你想要的是一个带有==重载的字符串数组类,意思是“比较每个可变长度的字符串,必要时将单个字符串广播到数组”。不幸的是,uprootObjectArrayStringArrayweird-array 中的类都还没有做到这一点。

因此,您可以这样做,当然是通过隐式 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 数组,它是(以填充为代价)。

替代方案,可能更好:

在写这篇文章的时候,我记得 uprootObjectArray是使用一个很尴尬的 实现的JaggedArray,所以上面的转换可以用JaggedArrayregular方法来实现,这可能要快得多(没有中间的 Pythonbytes对象,没有 Python for 循环)。

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

(上面描述的功能不是故意创建的,但它有效是因为正确的部分以偶然的方式组合在一起。)

2024-12-24