Konwertuje liczbę zmiennoprzecinkową na ints w Pandach?

230

Pracowałem z danymi importowanymi z pliku CSV. Pandy zmieniły niektóre kolumny na zmiennoprzecinkowe, więc teraz liczby w tych kolumnach są wyświetlane jako zmiennoprzecinkowe! Jednak muszę je wyświetlać jako liczby całkowite lub bez przecinka. Czy istnieje sposób przekonwertować je na liczby całkowite lub nie wyświetlać przecinka?

MJP
źródło
22
Możesz zmienić typ (o ile nie ma brakujących wartości)df.col = df.col.astype(int)
EdChum
To pytanie składa się z dwóch pytań jednocześnie, a tytuł tego pytania odzwierciedla tylko jedno z nich.
Monica Heddneck
Dla osób, które uderzają w powyższe i uważają, że są przydatne w koncepcji, ale nie działają dla ciebie, jest to wersja, która działała dla mnie w Pythonie 3.7.5 z df = df.astype(int)
pandami

Odpowiedzi:

216

Aby zmodyfikować wyjście float, wykonaj następujące czynności:

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
EdChum
źródło
16
Dzięki! Poprawiłem to w moim to_csv: fin.to_csv ('my_table.csv', float_format = '%. F'). Zadziałało!
MJP
4
W najnowszej wersji pand musisz dodać copy = False do argumentów astype, aby uniknąć ostrzeżenia
g.stevo
Czy trzeba to zrobić df.a = df.a.astype(float)? Czy to robi kopię (nie jestem pewien, jak używany jest copyparametr astype())? W każdym razie, aby zaktualizować typ „na miejscu”?
Mr_and_Mrs_D
1
@EdChum, czy istnieje sposób, aby zapobiec konwersji Pand na początku? Na przykład spróbuj DF.({'200': {'#': 354, '%': 0.9971830985915493}, '302': {'#': 1, '%': 0.0028169014084507044}}) Uwaga # przekonwertować na liczbę zmiennoprzecinkową i są to wiersze, a nie kolumny. ponieważ każdy z Seriesnich może przechowywać tylko jeden jednolity typ?
alancalvitti
@alancalvitti, jaki jest twój zamiar tutaj zachować wartości dtype? Jeśli tak, dtypeto musisz utworzyć te kolumny, ponieważ dtype objectpozwala to na mieszanie, w przeciwnym razie moja rada to po prostu użycie zmiennoprzecinkowe, a podczas porównańnp.isclose
EdChum
180

Użyj pandas.DataFrame.astype(<type>)funkcji do manipulowania typami kolumn.

>>> 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

EDYTOWAĆ:

Aby obsłużyć brakujące wartości:

>>> 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
Ryan G.
źródło
3
Próbowałem twoje podejście i daje mi ValueError: Nie można przekonwertować NA na liczbę całkowitą
MJP
6
@MJP Nie można przekonwertować serii z liczb zmiennoprzecinkowych na liczby całkowite, jeśli brakuje wartości, patrz pandas.pydata.org/pandas-docs/stable/… , należy użyć
liczb zmiennoprzecinkowych
2
Wartości nie brakuje, ale kolumna celowo nie określa wartości dla każdego wiersza. Czy istnieje sposób na obejście tego problemu? Ponieważ te wartości są identyfikatorami klucza obcego, potrzebuję ints.
MJP
4
Dokonałem edycji, w której wszystkie NaN są zastąpione przez 0,0.
Ryan G
3
Lub jeszcze lepiej, jeśli modyfikujesz tylko CSV, to: df.to_csv ("path.csv", na_rep = "", float_format = "%. 0f", index = False) Ale to spowoduje edycję wszystkich pływaków, więc może być lepiej przekonwertować kolumnę FK na ciąg, wykonać manipulację, a następnie zapisać.
Ryan G
44

Biorąc pod uwagę następującą ramkę danych:

>>> 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

Korzystając z listy nazw kolumn, zmień typ wielu kolumn za pomocą 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

Lub dla pojedynczej kolumny z 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
Jaroslav Bezděk
źródło
5
Co się stanie, jeśli w wartości będzie NaN?
Zhang18
3
@ Zhang18 Wypróbowałem to rozwiązanie, aw przypadku NaN masz ten błąd:ValueError: ('cannot convert float NaN to integer', u'occurred at index <column_name>')
enri
2
@enri: Można wypróbować następujący kod -df['C'] = df['C'].dropna().apply(np.int64)
vsdaking
12

Jest to szybkie rozwiązanie, jeśli chcesz przekonwertować więcej kolumn pandas.DataFramez liczb zmiennoprzecinkowych na liczbę całkowitą, biorąc pod uwagę również przypadek, w którym możesz mieć wartości 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 "")

Próbowałem z else x)i else None), ale wynik wciąż ma liczbę zmiennoprzecinkową, więc użyłem else "".

enri
źródło
zastosuje ""wszystkie wartości wcol
Raheel,
Zastosuje pusty ciąg („”) do wszystkich brakujących wartości, jeśli jest to wymagane, ale pozostałe wartości będą liczbami całkowitymi.
Krzysztof Słowiński
Dzięki za to. Działa to, gdy nie działają .astype () i .apply (np.int64).
Alison S,
To jest hacking i nie widzę powodu, aby używać go w stosunku do wielu dostępnych alternatyw.
AMC
8

Rozwijając @Ryan G wspomniane użycie pandas.DataFrame.astype(<type>)metody, można użyć errors=ignoreargumentu do konwersji tylko tych kolumn, które nie powodują błędu, co znacznie upraszcza składnię. Oczywiście należy zachować ostrożność przy ignorowaniu błędów, ale w przypadku tego zadania jest to bardzo przydatne.

>>> 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

Z dokumentów pandas.DataFrame.astype :

błędy: {„podbij”, „ignoruj”}, domyślnie „podbij”

Kontroluj zgłaszanie wyjątków dotyczących nieprawidłowych danych dla podanego typu.

  • podnieść: zezwalaj na zgłaszanie wyjątków
  • ignoruj: pomija wyjątki. W przypadku błędu zwróć oryginalny obiekt

Nowości w wersji 0.20.0.

aebmad
źródło
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
użytkownik8051244
źródło
5

Aby przekonwertować wszystkie zmiennoprzecinkowe kolumny na 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
Suhas_Pote
źródło
0

Oto prosta funkcja, która sprowadza spławik do najmniejszej możliwej liczby całkowitej, która nie traci żadnych informacji. Dla przykładów,

  • 100.0 można przekonwertować z liczby zmiennoprzecinkowej na liczbę całkowitą, ale 99,9 nie może (bez utraty informacji do zaokrąglania lub obcinania)

  • Dodatkowo 1.0 może być zesłane do końca int8bez utraty informacji, ale najmniejszym typem całkowitym dla 100_000.0 jestint32

Przykłady kodu:

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])
JohnE
źródło
0

Kolumny, które należy przekonwertować na int, można wymienić w słowniku również jak poniżej

df = df.astype({'col1': 'int', 'col2': 'int', 'col3': 'int'})
prashanth
źródło
-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
RAHUL KUMAR
źródło
1
astype(int)był już wspomniany kilka razy. Ta odpowiedź nie dodaje nic nowego.
Georgy,