Конвертировать поплавки в панды в броню?


230

Я работал с данными, импортированными из CSV. Панды изменили некоторые столбцы на плавающие, так что теперь числа в этих столбцах отображаются как плавающие точки! Однако мне нужно, чтобы они отображались в виде целых чисел или без запятой. Есть ли способ преобразовать их в целые числа или не отображать запятую?


22
Вы можете изменить тип (при условии, что отсутствуют пропущенные значения)df.col = df.col.astype(int)
EdChum

Этот вопрос представляет собой два вопроса одновременно, и название этого вопроса отражает только один из них.
Моника Хеднек

Для людей, которые используют вышесказанное и находят его полезным в концепции, но не работающим для вас, эта версия работала для меня в python 3.7.5 с пандами X:df = df.astype(int)
Oliver.R

Ответы:


218

Чтобы изменить вывод float, сделайте это:

df= pd.DataFrame(range(5), columns=['a'])
df.a = df.a.astype(float)
df

Out[33]:

          a
0 0.0000000
1 1.0000000
2 2.0000000
3 3.0000000
4 4.0000000

pd.options.display.float_format = '{:,.0f}'.format
df

Out[35]:

   a
0  0
1  1
2  2
3  3
4  4

16
Спасибо! Я изменил это в моем to_csv: fin.to_csv ('my_table.csv', float_format = '%. F'). Это сработало!
MJP

4
В последней версии панд вам нужно добавить copy = False к аргументам astype, чтобы избежать предупреждения
g.stevo

Это нужно сделать df.a = df.a.astype(float)? Делает ли это копию (не уверен, как используется copyпараметр to astype())? В любом случае обновить тип "на месте"?
Mr_and_Mrs_D

1
@EdChum, есть ли способ запретить Pandas преобразовывать типы для начала? Например, попробуйте DF.({'200': {'#': 354, '%': 0.9971830985915493}, '302': {'#': 1, '%': 0.0028169014084507044}}) Обратите внимание, что # преобразуется в число с плавающей точкой, и это строки, а не столбцы. потому что каждый из Seriesних может хранить только один единый тип?
alancalvitti

@alancalvitti каково ваше намерение сохранить ценности или dtype? Если это так, dtypeвам нужно создать эти столбцы так, dtype objectчтобы они допускали смешивание, в противном случае я бы посоветовал просто использовать float, а при сравнении использоватьnp.isclose
EdChum

180

Используйте pandas.DataFrame.astype(<type>)функцию для управления столбцами dtypes.

>>> df = pd.DataFrame(np.random.rand(3,4), columns=list("ABCD"))
>>> df
          A         B         C         D
0  0.542447  0.949988  0.669239  0.879887
1  0.068542  0.757775  0.891903  0.384542
2  0.021274  0.587504  0.180426  0.574300
>>> df[list("ABCD")] = df[list("ABCD")].astype(int)
>>> df
   A  B  C  D
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0

РЕДАКТИРОВАТЬ:

Для обработки пропущенных значений:

>>> df
          A         B     C         D
0  0.475103  0.355453  0.66  0.869336
1  0.260395  0.200287   NaN  0.617024
2  0.517692  0.735613  0.18  0.657106
>>> df[list("ABCD")] = df[list("ABCD")].fillna(0.0).astype(int)
>>> df
   A  B  C  D
0  0  0  0  0
1  0  0  0  0
2  0  0  0  0

3
Я попробовал ваш подход, и он дает мне ValueError: Невозможно преобразовать NA в целое число
MJP

6
@MJP Вы не можете конвертировать серии из числа с плавающей точкой в ​​целое число, если отсутствуют значения, см. Pandas.pydata.org/pandas-docs/stable/… , вы должны использовать числа с плавающей запятой
EdChum

2
Значения не пропущены, но в столбце специально не указывается значение для каждой строки. Есть ли способ добиться обхода? Поскольку эти значения являются идентификаторами внешних ключей, мне нужны целые числа.
MJP

4
Я сделал правку, в которой все NaN заменены на 0.0.
Райан Г

3
Или еще лучше, если вы изменяете только CSV, то: df.to_csv ("path.csv", na_rep = "", float_format = "%. 0f", index = False) Но это отредактирует все числа с плавающей точкой, поэтому может быть лучше преобразовать столбец FK в строку, выполнить манипуляции, а затем сохранить.
Райан Дж

44

Учитывая следующий кадр данных:

>>> df = pd.DataFrame(10*np.random.rand(3, 4), columns=list("ABCD"))
>>> print(df)
...           A         B         C         D
... 0  8.362940  0.354027  1.916283  6.226750
... 1  1.988232  9.003545  9.277504  8.522808
... 2  1.141432  4.935593  2.700118  7.739108

Используя список имен столбцов, измените тип для нескольких столбцов с помощью applymap():

>>> cols = ['A', 'B']
>>> df[cols] = df[cols].applymap(np.int64)
>>> print(df)
...    A  B         C         D
... 0  8  0  1.916283  6.226750
... 1  1  9  9.277504  8.522808
... 2  1  4  2.700118  7.739108

Или для одного столбца с apply():

>>> df['C'] = df['C'].apply(np.int64)
>>> print(df)
...    A  B  C         D
... 0  8  0  1  6.226750
... 1  1  9  9  8.522808
... 2  1  4  2  7.739108

5
Что если в значении есть NaN?
Zhang18

3
@ Zhang18 Я попробовал это решение, и в случае NaN у вас есть эта ошибка:ValueError: ('cannot convert float NaN to integer', u'occurred at index <column_name>')
enri

2
@enri: можно попробовать следующий кодdf['C'] = df['C'].dropna().apply(np.int64)
vsdaking

12

Это быстрое решение, если вы хотите преобразовать больше ваших столбцов из числа pandas.DataFrameс плавающей точкой в ​​целое, учитывая также случай, когда вы можете иметь значения NaN.

cols = ['col_1', 'col_2', 'col_3', 'col_4']
for col in cols:
   df[col] = df[col].apply(lambda x: int(x) if x == x else "")

Я попытался с else x)и else None), но результат все еще имеет число с плавающей запятой, поэтому я использовал else "".


он будет применен ""ко всем значениям вcol
Рахил

Он будет применять пустую строку ("") ко всем пропущенным значениям, если это то, что требуется, но остальные значения будут целочисленными.
Кшиштоф Словиньски

Спасибо за это. Это работало, когда .astype () и .apply (np.int64) не работали.
Элисон С.

Это кажется хакерским, и я не вижу причин использовать его из-за множества доступных альтернатив.
AMC

8

Расширяя @Ryan G упомянутое использование pandas.DataFrame.astype(<type>)метода, можно использовать errors=ignoreаргумент, чтобы преобразовать только те столбцы, которые не выдают ошибку, что значительно упрощает синтаксис. Очевидно, следует соблюдать осторожность при игнорировании ошибок, но для этой задачи это очень удобно.

>>> df = pd.DataFrame(np.random.rand(3, 4), columns=list('ABCD'))
>>> df *= 10
>>> print(df)
...           A       B       C       D
... 0   2.16861 8.34139 1.83434 6.91706
... 1   5.85938 9.71712 5.53371 4.26542
... 2   0.50112 4.06725 1.99795 4.75698

>>> df['E'] = list('XYZ')
>>> df.astype(int, errors='ignore')
>>> print(df)
...     A   B   C   D   E
... 0   2   8   1   6   X
... 1   5   9   5   4   Y
... 2   0   4   1   4   Z

Из документов pandas.DataFrame.astype :

ошибки: {'повысить', 'игнорировать'}, по умолчанию 'поднять'

Контроль возникновения исключений для недействительных данных для предоставленного dtype.

  • поднять: разрешить возбудить исключения
  • игнорировать: исключать исключения. При ошибке вернуть исходный объект

Новое в версии 0.20.0.


7
>>> import pandas as pd
>>> right = pd.DataFrame({'C': [1.002, 2.003], 'D': [1.009, 4.55], 'key': ['K0', 'K1']})
>>> print(right)
           C      D key
    0  1.002  1.009  K0
    1  2.003  4.550  K1
>>> right['C'] = right.C.astype(int)
>>> print(right)
       C      D key
    0  1  1.009  K0
    1  2  4.550  K1

5

Чтобы преобразовать все столбцы с плавающей точкой в ​​int

>>> df = pd.DataFrame(np.random.rand(5, 4) * 10, columns=list('PQRS'))
>>> print(df)
...     P           Q           R           S
... 0   4.395994    0.844292    8.543430    1.933934
... 1   0.311974    9.519054    6.171577    3.859993
... 2   2.056797    0.836150    5.270513    3.224497
... 3   3.919300    8.562298    6.852941    1.415992
... 4   9.958550    9.013425    8.703142    3.588733

>>> float_col = df.select_dtypes(include=['float64']) # This will select float columns only
>>> # list(float_col.columns.values)
>>> for col in float_col.columns.values:
...     df[col] = df[col].astype('int64')
>>> print(df)
...     P   Q   R   S
... 0   4   0   8   1
... 1   0   9   6   3
... 2   2   0   5   3
... 3   3   8   6   1
... 4   9   9   8   3

0

Вот простая функция, которая будет понижать число с плавающей точкой до наименьшего возможного целочисленного типа, который не теряет никакой информации. Например,

  • 100.0 может быть преобразовано из числа с плавающей точкой в ​​целое число, но 99.9 не может (без потери информации для округления или усечения)

  • Кроме того, 1.0 может быть int8уменьшен до полной потери информации, но наименьший целочисленный тип для 100_000.0int32

Примеры кода:

import numpy as np
import pandas as pd

def float_to_int( s ):
    if ( s.astype(np.int64) == s ).all():
        return pd.to_numeric( s, downcast='integer' )
    else:
        return s

# small integers are downcast into 8-bit integers
float_to_int( np.array([1.0,2.0]) )
Out[1]:array([1, 2], dtype=int8)

# larger integers are downcast into larger integer types
float_to_int( np.array([100_000.,200_000.]) )
Out[2]: array([100000, 200000], dtype=int32)

# if there are values to the right of the decimal
# point, no conversion is made
float_to_int( np.array([1.1,2.2]) )
Out[3]: array([ 1.1,  2.2])

0

Столбцы, которые нужно преобразовать в int, могут быть упомянуты в словаре, как показано ниже

df = df.astype({'col1': 'int', 'col2': 'int', 'col3': 'int'})

-5
>>> df_18['cyl'].value_counts()
... 4.0     365
... 6.0     246
... 8.0     153

>>> df_18['cyl'] = df_18['cyl'].astype(int)
>>> df_18['cyl'].value_counts()
... 4     365
... 6     246
... 8     153

1
astype(int)уже упоминалось несколько раз. Этот ответ не добавляет ничего нового.
Георгий
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.