Строки в DataFrame, но dtype - это объект


96

Почему Pandas сообщает мне, что у меня есть объекты, хотя каждый элемент в выбранном столбце является строкой - даже после явного преобразования.

Это мой DataFrame:

<class 'pandas.core.frame.DataFrame'>
Int64Index: 56992 entries, 0 to 56991
Data columns (total 7 columns):
id            56992  non-null values
attr1         56992  non-null values
attr2         56992  non-null values
attr3         56992  non-null values
attr4         56992  non-null values
attr5         56992  non-null values
attr6         56992  non-null values
dtypes: int64(2), object(5)

Их пять dtype object. Я явно конвертирую эти объекты в строки:

for c in df.columns:
    if df[c].dtype == object:
        print "convert ", df[c].name, " to string"
        df[c] = df[c].astype(str)

Тогда df["attr2"]все еще есть dtype object, хотя type(df["attr2"].ix[0]показывает str, что это правильно.

Панды различают int64и float64и object. Какая логика за этим, когда нет dtype str? Почему strпокрыто object?


Пришел сюда, потому что соединения не работают из-за "типа объекта", хотя каждая строка "есть"
Моника Хедднек

Ответы:


145

Объект dtype происходит от NumPy, он описывает тип элемента в ndarray. Каждый элемент в ndarray должен иметь одинаковый размер в байтах. Для int64 и float64 это 8 байтов. Но для строк длина строки не фиксирована. Поэтому вместо того, чтобы сохранять байты строк в ndarray напрямую, Pandas использует объект ndarray, который сохраняет указатели на объекты, из-за этого dtype этого типа ndarray является объектом.

Вот пример:

  • массив int64 содержит 4 значения int64.
  • массив объектов содержит 4 указателя на 3 строковых объекта.

введите описание изображения здесь


3
Однако обратите внимание на то, что наличие столбцов типа «объект» имеет большое влияние на производительность операций чтения / записи
DataFrame

Могу ли я каким-то образом получить тип данных, возвращенный в виде строки. Я знаю, что всегда могу использовать type (df ["column"]. Iloc [0]), но может случиться так, что это nan
user1953366

7

Принятый ответ хорош. Просто хотел дать ответ со ссылкой на документацию . В документации говорится:

Pandas использует объект dtype для хранения строк.

Как говорится в ведущем комментарии: «Не беспокойтесь об этом, так должно быть». (Хотя принятый ответ отлично объяснил «почему»; строки имеют переменную длину)

Но для строк длина строки не фиксирована.


Почему мне нужно преобразовать каждый столбец, который я передаю, в scipy или sklearn astype (str), чтобы он его принял? кажется, я должен сначала применить это ко всем столбцам.
Tinkinc

Я не понимаю; @Tinkinc, что произойдет, если вы не конвертируете столбцы в строку? И этот ответ кажется элегантным способом преобразовать все столбцы в,astype(str) хотя я все еще удивляюсь, что преобразование строк необходимо
Red Pea

Я не могу заполнить (0) все объекты в моем фрейме данных остаются (1, nan) вместо (1,0)
Tinkinc

Извините, @Tinkinc, я все еще не понимаю; Я хочу помочь, но ваша проблема кажется более сложной, чем комментарий о переполнении стека. Вы можете задать вопрос или присоединиться ко мне в чате. (только что пригласил вас)
The Red Pea

5

Ответ @ HYRY отличный. Я просто хочу дать немного больше контекста ...

Массивы хранятся данные , как непрерывный , фиксированного размера блоков памяти. Сочетание этих свойств вместе делает массивы молниеносными для доступа к данным. Например, рассмотрим , как ваш компьютер может хранить массив 32-битных целых чисел, [3,0,1].

введите описание изображения здесь

Если вы попросите свой компьютер получить 3-й элемент в массиве, он начнется с начала, а затем перейдет через 64 ​​бита, чтобы перейти к 3-му элементу. Точное знание того, через сколько битов нужно перескочить, делает массивы быстрыми .

Теперь рассмотрим последовательность строк ['hello', 'i', 'am', 'a', 'banana']. Строки - это объекты, которые различаются по размеру, поэтому, если вы попытаетесь сохранить их в смежных блоках памяти, это будет выглядеть так.

введите описание изображения здесь

Теперь у вашего компьютера нет быстрого доступа к случайно запрошенному элементу. Ключ к преодолению этого - использование указателей. По сути, храните каждую строку в некотором случайном месте памяти и заполняйте массив адресом памяти каждой строки. (Адреса памяти - это просто целые числа.) Теперь все выглядит так:

введите описание изображения здесь

Теперь, если вы попросите свой компьютер получить 3-й элемент, как и раньше, он может перескочить через 64 ​​бита (при условии, что адреса памяти - 32-битные целые числа), а затем сделать один дополнительный шаг, чтобы получить строку.

Проблема для NumPy заключается в том, что нет гарантии, что указатели действительно указывают на строки. Вот почему он сообщает dtype как «объект».

Без зазрения совести вставлю статью в свой блог, где я изначально это обсуждал.


Красиво написано
..

1

Начиная с версии 1.0.0 (январь 2020 г.), pandas представлена ​​как экспериментальная функция, обеспечивающая первоклассную поддержку строковых типов через pandas.StringDtype.

Хотя вы по-прежнему будете видеть objectпо умолчанию, новый тип можно использовать, указав dtypeиз pd.StringDtypeили просто 'string':

>>> pd.Series(['abc', None, 'def'])
0     abc
1    None
2     def
dtype: object
>>> pd.Series(['abc', None, 'def'], dtype=pd.StringDtype())
0     abc
1    <NA>
2     def
dtype: string
>>> pd.Series(['abc', None, 'def']).astype('string')
0     abc
1    <NA>
2     def
dtype: string

2
Не используйте это ... пока. Как они заявили, The implementation may change without warning.это означает , что новые обновления сломают ваши старые программы.
NoName

1
Ну, все зависит от того, для чего вы собираетесь его использовать. Если вы хотите использовать его в производственной системе, где необходимы постоянные обновления пакетов и где поломка API вызывает неприемлемую нагрузку на обслуживание, тогда обязательно обратите пристальное внимание на слово «экспериментальный», но если вы используете pandas для выполнения исследовательских задач. анализ в сценариях, время жизни которых не увеличивает рабочий день, то эти опасения не должны ничего значить для вас.
fuglede

Начиная с Pandas 1.1, API кажется стабилизированным. Все типы dtypes теперь могут быть преобразованы в StringDtype .
D3f0
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.