Какие структуры numpy ожидаются в качестве входных данных для использования функций numpy.char? - PullRequest
1 голос
/ 28 апреля 2019

Рассмотрим небольшой массив массивов строк (по крайней мере, мой самый близкий взгляд на то, как это сделать):

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 ]

1 голос
/ 28 апреля 2019

Тип строки в параметре должен соответствовать типу в массиве:

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' - bytestring, тип по умолчанию для Py2.b':' - строка байтов, u':' - юникод.

Этот np.char.split немного неудобен в использовании, так как в результате получается объект типа d со списками разделенных строк.

Чтобы получить 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')

Я мог бы объединить распаковку и astype с np.vectorize, предоставив otypes (даже смесь dtypes!):

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

Обычно frompyfunc быстрее, чем vectorize.

Эта распаковка не будет работать, если разделение создает списки различной длины:

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 для быстрых векторизованных строковых операций..

1 голос
/ 28 апреля 2019

Во-первых, функции np.char предназначены для работы на chararrays, который должен быть составлен с np.char.array или np.char.asarray (см. документы ).

Соответственно, ваш код будет работать так:

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]

Для полноты, ваш вспомогательный вопрос о <U4 против S5:

A numpy dtype с U означает строку в юникоде, которая является рекомендуемым способом представления строк . С другой стороны, S представляет байтовый массив с нулевым символом в конце.

Я подозреваю, что строковые методы выполняются над объектами Python, и поэтому вам нужен строковый тип Python (знает свою длину и т. Д.), А не "тупой" строковый байтовый массив Си.

...