1

我有一棵树,它的一个分支存储着一根绳子。当我阅读 usinguproot.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 ()

有人对如何进行有任何建议吗?能够将其转换为 anumpy.chararray已经可以解决问题,但我不知道该怎么做。

4

1 回答 1

0

字符串处理是 uproot 的一个弱点。它使用自定义ObjectArray(甚至不是StringArrayin 笨拙的数组),bytes按需生成对象。您想要的是一个字符串数组类,其==重载表示“比较每个可变长度字符串,如有必要,将单个字符串广播到数组”。不幸的是,ObjectArray字符串的连根拔起和StringArray笨拙数组中的类都没有这样做。

所以这就是你如何做到这一点,诚然,通过一个隐式的 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,所以上面的转换可以用JaggedArray'regular方法执行,这可能要快得多(没有中间 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])

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

于 2019-11-18T21:45:09.877 回答