预期使用什么numpy结构作为使用numpy.char函数的输入?

时间:2019-04-28 12:30:58

标签: python string numpy numpy-ndarray

考虑一个字符串数组的numpy数组(至少我最接近的做法):

ff = np.array([['a:bc','d:ef'],['g:hi','j:kl']])
print(ff.dtype)
<U4

但是这些显然不能与numpy.char方法一起使用..?

ffc = ff.astype('S5')
fff = np.char.split(ffc,':')[1]


Traceback (most recent call last):
  File "<input>", line 3, in <module>
  File "/usr/local/lib/python3.7/site-packages/numpy/core/defchararray.py", line 1447, in split
    a, object_, 'split', [sep] + _clean_args(maxsplit))
TypeError: a bytes-like object is required, not 'numpy.str_'

<U4.str_类型之间有什么区别?np.char.**如何解析显示的字符串?

2 个答案:

答案 0 :(得分:1)

首先,np.char函数应在chararrays上工作,该函数应使用np.char.arraynp.char.asarray构造(请参见docs)。 / p>

因此,您给定的代码将像这样工作:

ff = np.array([['a:bc','d:ef'],['g:hi','j:kl']])
ffc = np.char.asarray(ff)
fff = np.char.split(ffc, ':')[1]

print(fff)

输出:

[list(['g', 'hi']) list(['j', 'kl'])]

此转换是隐式执行的,因此,实际上,它也可以工作:

ff = np.array([['a:bc','d:ef'],['g:hi','j:kl']])
fff = np.char.split(ff, ':')[1]

为完整起见,关于<U4S5的附属问题:

带有numpy的{​​{1}} dtype表示一个unicode字符串,即recommended way of representing strings。另一方面,U代表以空值结尾的字节数组。

我的怀疑是,字符串方法是在Python对象上执行的,因此,您需要一个类似Python字符串的类型(知道其自身的长度等),而不是一个“笨拙的” C字符串类型的字节数组。 >

答案 1 :(得分:1)

参数中的字符串类型必须与数组中的类型匹配:

In [44]: ff = np.array([['a:bc','d:ef'],['g:hi','j:kl']])                            
In [45]: ff                                                                          
Out[45]: 
array([['a:bc', 'd:ef'],
       ['g:hi', 'j:kl']], dtype='<U4')
In [46]: np.char.split(ff,':')                                                       
Out[46]: 
array([[list(['a', 'bc']), list(['d', 'ef'])],
       [list(['g', 'hi']), list(['j', 'kl'])]], dtype=object)
In [47]: np.char.split(ff.astype('S5'),b':')                                         
Out[47]: 
array([[list([b'a', b'bc']), list([b'd', b'ef'])],
       [list([b'g', b'hi']), list([b'j', b'kl'])]], dtype=object)

'U4'是unicode,是Py3的默认字符串类型。 “ S4”是字节串,是Py2的默认类型。 b':'是一个字节字符串,u':'是unicode。

np.char.split使用起来有点尴尬,因为结果是带有分割字符串列表的对象dtype。

要获得2个单独的数组,我将使用frompyfunc进行拆包:

In [50]: np.frompyfunc(lambda alist: tuple(alist), 1,2)(_46)                         
Out[50]: 
(array([['a', 'd'],
        ['g', 'j']], dtype=object), array([['bc', 'ef'],
        ['hi', 'kl']], dtype=object))
In [51]: np.frompyfunc(lambda alist: tuple(alist), 1,2)(_47)                         
Out[51]: 
(array([[b'a', b'd'],
        [b'g', b'j']], dtype=object), array([[b'bc', b'ef'],
        [b'hi', b'kl']], dtype=object))

尽管要获取字符串dtype数组,我仍将使用astype

In [52]: _50[0].astype('U4')                                                         
Out[52]: 
array([['a', 'd'],
       ['g', 'j']], dtype='<U4')

我可以通过提供np.vectorize(甚至是dtypes的混合!)来将拆包和astype与otypes结合起来:

In [53]: np.vectorize(lambda alist:tuple(alist), otypes=['U4','S4'])(_46)            
Out[53]: 
(array([['a', 'd'],
        ['g', 'j']], dtype='<U1'), array([[b'bc', b'ef'],
        [b'hi', b'kl']], dtype='|S2'))

通常frompyfuncvectorize快。

如果拆分创建了不同的长度列表,则此拆包将不起作用:

In [54]: ff = np.array([['a:bc','d:ef'],['g:hi','j:kl:xyz']])                        
In [55]: np.char.split(ff,':')                                                       
Out[55]: 
array([[list(['a', 'bc']), list(['d', 'ef'])],
       [list(['g', 'hi']), list(['j', 'kl', 'xyz'])]], dtype=object)

===

有了chararray,所有这些np.char函数都可以用作方法。

In [59]: np.char.asarray(ff)                                                         
Out[59]: 
chararray([['a:bc', 'd:ef'],
           ['g:hi', 'j:kl:xyz']], dtype='<U8')
In [60]: np.char.asarray(ff).split(':')                                              
Out[60]: 
array([[list(['a', 'bc']), list(['d', 'ef'])],
       [list(['g', 'hi']), list(['j', 'kl', 'xyz'])]], dtype=object)

请参阅np.char文档中的注释:

  

存在chararray类是为了向后兼容      Numarray,不建议用于新开发。从numpy开始      1.4,如果需要一个字符串数组,建议使用      dtype object_string_unicode_,并使用免费功能      在numpy.char模块中进行快速矢量化字符串操作。