In [313]: arr = np.array(['one','twenty'])
In [314]: arr
Out[314]: array(['one', 'twenty'], dtype='<U6')
In [315]: arr.astype(object)
Out[315]: array(['one', 'twenty'], dtype=object)
np.char
применяет строковые методы к элементам строкового массива dtype:
In [316]: np.char.add(arr, ' foo')
Out[316]: array(['one foo', 'twenty foo'], dtype='<U10')
add
не определено для типов строк numpy:
In [317]: np.add(arr, ' foo')
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-317-eff87c160b77> in <module>
----> 1 np.add(arr, ' foo')
TypeError: ufunc 'add' did not contain a loop with signature matching types dtype('<U6') dtype('<U6') dtype('<U6')
Это использование np.add
превращает строку 'foo' в массив, прежде чем пытаться ее использовать. Он пытается добавить строку «U6» в строку «U6».
np.add
при применении к массиву dtype объекта делегирует действие соответствующему методу элементов. Поскольку add
определено для строк Python, оно работает:
In [318]: np.add(arr.astype(object), ' foo')
Out[318]: array(['one foo', 'twenty foo'], dtype=object)
Этот шаблон распространяется на всех NumPy ufunc
. Они определены для конкретных dtypes
. Если дано object
dtypes, они делегируют - что может работать или не работать в зависимости от методов элементов.
Оба подхода object
и np.char
эквивалентны пониманию списка и примерно с одинаковой скоростью:
In [324]: [i+' foo' for i in arr]
Out[324]: ['one foo', 'twenty foo']
===
Пример с репликацией строк *
In [319]: arr*2
TypeError: ufunc 'multiply' did not contain a loop with signature matching types dtype('<U6') dtype('<U6') dtype('<U6')
In [320]: arr.astype(object)*2
Out[320]: array(['oneone', 'twentytwenty'], dtype=object)
In [322]: np.char.multiply(arr,2)
Out[322]: array(['oneone', 'twentytwenty'], dtype='<U12')