Перетворити поплавці в ints в Pandas?


230

Я працював з даними, імпортованими з CSV. Панди змінили деякі стовпці на плаваючі, тому тепер цифри в цих стовпцях відображаються як плаваючі точки! Однак мені потрібно, щоб вони відображалися як цілі числа, або без коми. Чи є спосіб перетворити їх на цілі числа чи не відобразити кому?


22
Ви можете змінити тип (доки не буде відсутніх значень)df.col = df.col.astype(int)
EdChum

Це запитання одночасно є двома питаннями, а назва цього питання відображає лише одне з них.
Моніка Геднек

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

Відповіді:


216

Щоб змінити вихід поплавця, зробіть це:

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 до аргументів астипе, щоб уникнути попередження
g.stevo

Це потрібно робити df.a = df.a.astype(float)? Це робить копію (не впевнений, як використовується copyпараметр astype())? У будь-якому випадку, щоб оновити тип "на місці"?
Mr_and_Mrs_D

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

@alancalvitti, який ви маєте намір зберегти ціннісні значення чи dtype? Якщо це dtypeтоді, вам потрібно створити ці стовпці dtype objectтак, що це дозволяє змішати, інакше моя порада буде просто використовувати float, а при використанні порівняньnp.isclose
EdChum

180

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

>>> 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 Ви не можете перетворити ряд з float в ціле число, якщо відсутні значення, див. Pandas.pydata.org/pandas-docs/stable/… , ви повинні використовувати
floats

2
Значення не відсутні, але стовпець не задає значення для кожного рядка за призначенням. Чи є спосіб досягти обходу? Оскільки ці значення - ідентифікатори іноземних ключів, мені потрібні вставки.
MJP

4
Я вніс редагування, в якому всі NaN замінені на 0,0.
Ryan G

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?
Чжан18

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) не зробили це.
Елісон S

Це відчувається хакі, і я не бачу причин використовувати його для багатьох доступних альтернатив.
AMC

8

Розширюючи згадане використання pandas.DataFrame.astype(<type>)методу на @Ryan G , можна використовувати 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 :

помилки: {'підвищити', 'ігнорувати'}, за замовчуванням 'підняти'

Контроль підвищення винятків щодо недійсних даних для наданого типу.

  • підвищувати: дозволяти збільшувати винятки
  • ignore: придушити винятки. При поверненні помилки вихідний об'єкт

Нове у версії 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.0 єint32

Приклади коду:

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.