Floats in Ints in Pandas konvertieren?

228

Ich habe mit Daten gearbeitet, die aus einer CSV importiert wurden. Pandas haben einige Spalten in Gleitkomma geändert, sodass die Zahlen in diesen Spalten jetzt als Gleitkommazahlen angezeigt werden! Sie müssen jedoch als Ganzzahlen oder ohne Komma angezeigt werden. Gibt es eine Möglichkeit, sie in Ganzzahlen umzuwandeln oder das Komma nicht anzuzeigen?

MJP
quelle
22
Sie können den Typ ändern (solange keine Werte fehlen)df.col = df.col.astype(int)
EdChum
Diese Frage besteht aus zwei Fragen gleichzeitig, und der Titel dieser Frage spiegelt nur eine davon wider.
Monica Heddneck
Für Leute, die das oben Genannte treffen und es im Konzept nützlich finden, aber nicht für Sie arbeiten, ist dies die Version, die für mich in Python 3.7.5 mit Pandas X df = df.astype(int)
funktioniert hat

Antworten:

214

Gehen Sie folgendermaßen vor, um die Float-Ausgabe zu ändern:

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
quelle
16
Vielen Dank! Ich habe dies in meinem to_csv: fin.to_csv ('my_table.csv', float_format = '%. F') angepasst. Es funktionierte!
MJP
4
In der neuesten Version von Pandas müssen Sie copy = False zu den Argumenten von astype hinzufügen, um eine Warnung zu vermeiden
g.stevo
Muss es getan werden df.a = df.a.astype(float)? copyErstellt dies eine Kopie (nicht sicher, wie der Parameter astype()verwendet wird)? Wie auch immer, um den Typ "an Ort und Stelle" zu aktualisieren?
Mr_and_Mrs_D
1
@EdChum, gibt es eine Möglichkeit zu verhindern, dass Pandas zunächst Typen konvertieren? Beispiel: DF.({'200': {'#': 354, '%': 0.9971830985915493}, '302': {'#': 1, '%': 0.0028169014084507044}}) Beachten Sie, dass das # in float konvertiert wird und es sich um Zeilen und nicht um Spalten handelt. weil jeder ein ist, Seriesder nur einen einzigen einheitlichen Typ speichern kann?
Alancalvitti
@alancalvitti was ist deine absicht hier um die werte zu bewahren oder die dtype? Wenn dies der Fall ist, dtypemüssen Sie diese Spalten dtype objectso erstellen, dass sie gemischt werden können. Andernfalls würde ich np.isclose
empfehlen
179

Verwenden Sie die pandas.DataFrame.astype(<type>)Funktion, um Spalten-dtypes zu bearbeiten.

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

BEARBEITEN:

So behandeln Sie fehlende Werte:

>>> 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.
quelle
3
Ich habe Ihren Ansatz ausprobiert und er gibt mir einen ValueError: NA kann nicht in eine Ganzzahl konvertiert werden
MJP
6
@MJP Sie können keine Serien von float in integer konvertieren, wenn Werte fehlen. Siehe pandas.pydata.org/pandas-docs/stable/… . Sie müssen
float
2
Die Werte fehlen nicht, aber in der Spalte wird nicht absichtlich für jede Zeile ein Wert angegeben. Gibt es eine Möglichkeit, eine Problemumgehung zu erreichen? Da diese Werte Fremdschlüssel-IDs sind, benötige ich Ints.
MJP
4
Ich habe eine Bearbeitung vorgenommen, bei der alle NaNs durch eine 0.0 ersetzt werden.
Ryan G
3
Oder noch besser, wenn Sie nur eine CSV ändern, dann: df.to_csv ("path.csv", na_rep = "", float_format = "%. 0f", index = False) Aber dies wird alle Floats bearbeiten, also Es ist möglicherweise besser, die FK-Spalte in eine Zeichenfolge zu konvertieren, die Manipulation durchzuführen und dann zu speichern.
Ryan G
44

Betrachtet man den folgenden Datenrahmen:

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

Ändern Sie mithilfe einer Liste von Spaltennamen den Typ für mehrere Spalten mit 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

Oder für eine einzelne Spalte mit 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
quelle
5
Was ist, wenn der Wert ein NaN enthält?
Zhang18
3
@ Zhang18 Ich habe diese Lösung ausprobiert und im Falle von NaN haben Sie diesen Fehler:ValueError: ('cannot convert float NaN to integer', u'occurred at index <column_name>')
Enri
2
@enri: Kann versuchen, den folgenden Code -df['C'] = df['C'].dropna().apply(np.int64)
vsdaking
12

Dies ist eine schnelle Lösung pandas.DataFramefür den Fall, dass Sie mehr Spalten von float in integer konvertieren möchten, auch wenn Sie NaN-Werte haben können.

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

Ich habe es mit else x)und versucht else None), aber das Ergebnis hat immer noch die Float-Nummer, also habe ich verwendet else "".

enri
quelle
es wird das ""auf alle Werte incol
Raheel
Es wird eine leere Zeichenfolge ("") auf alle fehlenden Werte angewendet, wenn dies erforderlich ist, der Rest der Werte ist jedoch eine Ganzzahl.
Krzysztof Słowiński
Danke dafür. Dies funktionierte, wenn .astype () und .apply (np.int64) dies nicht taten.
Alison S
Das fühlt sich hackig an, und ich sehe keinen Grund, es über die vielen verfügbaren Alternativen hinweg zu verwenden.
AMC
8

Wenn man die von @Ryan G erwähnte Verwendung der pandas.DataFrame.astype(<type>)Methode erweitert, kann man das errors=ignoreArgument verwenden, um nur die Spalten zu konvertieren, die keinen Fehler erzeugen, was die Syntax erheblich vereinfacht. Natürlich sollte beim Ignorieren von Fehlern Vorsicht walten lassen, aber für diese Aufgabe ist es sehr praktisch.

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

Aus pandas.DataFrame.astype- Dokumenten:

Fehler: {'erhöhen', 'ignorieren'}, Standard 'erhöhen'

Kontrollieren Sie das Auslösen von Ausnahmen für ungültige Daten für den angegebenen dtype.

  • erhöhen: Ausnahmen zulassen
  • ignorieren: Ausnahmen unterdrücken. Bei einem Fehler das ursprüngliche Objekt zurückgeben

Neu in Version 0.20.0.

aebmad
quelle
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
user8051244
quelle
5

So konvertieren Sie alle Float-Spalten in 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
quelle
0

Hier ist eine einfache Funktion, mit der Floats in den kleinstmöglichen Integer-Typ verschoben werden, der keine Informationen verliert. Zum Beispiel,

  • 100.0 kann von float in integer konvertiert werden, 99.9 jedoch nicht (ohne Informationen durch Rundung oder Kürzung zu verlieren).

  • Darüber hinaus kann 1.0 bis zum int8Verlust von Informationen heruntergestuft werden , der kleinste ganzzahlige Typ für 100_000.0 ist jedochint32

Codebeispiele:

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

Die Spalten, die in int konvertiert werden müssen, können in einem Wörterbuch auch wie folgt erwähnt werden

df = df.astype({'col1': 'int', 'col2': 'int', 'col3': 'int'})
Prashanth
quelle
-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
quelle
1
astype(int)wurde bereits mehrfach erwähnt. Diese Antwort fügt nichts Neues hinzu.
Georgy