Pandas различие между строками и объектами

Кажется, что Numpy делает различие между типами str и object. Например, я могу сделать:

>>> import pandas as pd
>>> import numpy as np
>>> np.dtype(str)
dtype('S')
>>> np.dtype(object)
dtype('O')

Где dtype ('S') и dtype ('O') соответствуют str и object соответственно.

Однако pandas, похоже, не имеет такого различия и принуждения str до object.::

>>> df = pd.DataFrame({'a': np.arange(5)})
>>> df.a.dtype
dtype('int64')
>>> df.a.astype(str).dtype
dtype('O')
>>> df.a.astype(object).dtype
dtype('O')

Принуждение к типу dtype('S') тоже не помогает.::

>>> df.a.astype(np.dtype(str)).dtype
dtype('O')
>>> df.a.astype(np.dtype('S')).dtype
dtype('O')

Есть ли объяснения этого поведения?

Ответ 1

Дескрипторы numpy string не являются строками python.

Следовательно, pandas намеренно использует собственные строки python, для которых требуется объект dtype.

Прежде всего, позвольте мне немного продемонстрировать, что я имею в виду, когда numpy strings отличаются:

In [1]: import numpy as np
In [2]: x = np.array(['Testing', 'a', 'string'], dtype='|S7')
In [3]: y = np.array(['Testing', 'a', 'string'], dtype=object)

Теперь 'x' является строкой dtype numpy (фиксированная ширина, c-подобная строка) и y является массивом собственных строк python.

Если мы попытаемся выйти за пределы 7 символов, мы увидим немедленную разницу. Строковые версии dtype будут усечены:

In [4]: x[1] = 'a really really really long'
In [5]: x
Out[5]:
array(['Testing', 'a reall', 'string'],
      dtype='|S7')

В то время как версии dtype объекта могут быть произвольной длиной:

In [6]: y[1] = 'a really really really long'

In [7]: y
Out[7]: array(['Testing', 'a really really really long', 'string'], dtype=object)

Далее, строки |S dtype не могут содержать юникод должным образом, хотя также существует строка dtype с фиксированной длиной unicode. На данный момент я пропущу пример.

Наконец, numpy-строки на самом деле изменяемы, а строки Python - нет. Например:

In [8]: z = x.view(np.uint8)
In [9]: z += 1
In [10]: x
Out[10]:
array(['Uftujoh', 'b!sfbmm', 'tusjoh\x01'],
      dtype='|S7')

По всем этим причинам pandas предпочла никогда не допускать, чтобы строки типа C с фиксированной длиной как тип данных. Как вы заметили, попытка принудить строку python к фиксированной строке с numpy не будет работать в pandas. Вместо этого он всегда использует собственные строки python, которые ведут себя более интуитивно понятным способом для большинства пользователей.

Ответ 2

Как вы можете выполнить сравнение строк с объектами тогда? Например, сравнивая два столбца?