Convertir des flotteurs en pouces dans Pandas?

230

J'ai travaillé avec des données importées d'un CSV. Les pandas ont changé certaines colonnes pour qu'elles flottent, alors maintenant les nombres dans ces colonnes s'affichent en virgule flottante! Cependant, j'ai besoin qu'ils soient affichés sous forme d'entiers ou sans virgule. Existe-t-il un moyen de les convertir en entiers ou de ne pas afficher la virgule?

MJP
la source
22
Vous pouvez changer le type (tant qu'il n'y a pas de valeurs manquantes)df.col = df.col.astype(int)
EdChum
Cette question est deux questions en même temps, et le titre de cette question ne reflète qu'une seule d'entre elles.
Monica Heddneck
Pour un peuple frappant ce qui précède et le trouvant utile dans le concept mais ne travaillant pas pour vous, c'est la version qui a fonctionné pour moi en python 3.7.5 avec pandas X:df = df.astype(int)
Oliver.R

Réponses:

217

Pour modifier la sortie flottante, procédez comme suit:

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
la source
16
Merci! J'ai ajusté cela dans mon to_csv: fin.to_csv ('my_table.csv', float_format = '%. F'). Ça a marché!
MJP
4
Dans la dernière version de pandas, vous devez ajouter copy = False aux arguments de astype pour éviter un avertissement
g.stevo
Faut-il faire df.a = df.a.astype(float)? Cela fait-il une copie (vous ne savez pas comment le copyparamètre astype()est utilisé)? Quoi qu'il en soit pour mettre à jour le type "en place"?
Mr_and_Mrs_D
1
@EdChum, existe-t-il un moyen d'empêcher les pandas de convertir les types pour commencer? Par exemple, essayez de DF.({'200': {'#': 354, '%': 0.9971830985915493}, '302': {'#': 1, '%': 0.0028169014084507044}}) noter que le # est converti en float et ce sont des lignes, pas des colonnes. parce que chacun est un Seriesqui ne peut stocker qu'un seul type uniforme?
alancalvitti
@alancalvitti quelle est votre intention ici de préserver les valeurs ou les dtype? Si c'est le cas, dtypevous devez créer ces colonnes de dtype objectmanière à ce qu'elles soient mélangées, sinon mon conseil serait d'utiliser simplement float et lors des comparaisons, utiliseznp.isclose
EdChum
180

Utilisez la pandas.DataFrame.astype(<type>)fonction pour manipuler les types de colonne.

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

ÉDITER:

Pour gérer les valeurs manquantes:

>>> 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
la source
3
J'ai essayé votre approche et cela me donne une ValueError: Impossible de convertir NA en entier
MJP
6
@MJP Vous ne pouvez pas convertir des séries de float en entier s'il y a des valeurs manquantes voir pandas.pydata.org/pandas-docs/stable/… , vous devez utiliser des floats
EdChum
2
Les valeurs ne sont pas manquantes, mais la colonne ne spécifie pas de valeur pour chaque ligne à dessein. Existe-t-il un moyen de contourner ce problème? Étant donné que ces valeurs sont des identifiants de clé étrangère, j'ai besoin d'ints.
MJP
4
J'ai fait un montage dans lequel tous les NaN sont remplacés par un 0.0.
Ryan G
3
Ou mieux encore, si vous ne modifiez qu'un CSV, alors: df.to_csv ("path.csv", na_rep = "", float_format = "%. 0f", index = False) Mais cela éditera tous les flottants, donc il peut être préférable de convertir votre colonne FK en une chaîne, de faire la manipulation, puis de l'enregistrer.
Ryan G du
44

Compte tenu de la trame de données suivante:

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

À l'aide d'une liste de noms de colonnes, modifiez le type de plusieurs colonnes avec 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

Ou pour une seule colonne avec 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
la source
5
Et s'il y a un NaN dans la valeur?
Zhang18
3
@ Zhang18 J'ai essayé cette solution et en cas de NaN vous avez cette erreur:ValueError: ('cannot convert float NaN to integer', u'occurred at index <column_name>')
enri
2
@enri: Peut essayer le code suivant -df['C'] = df['C'].dropna().apply(np.int64)
vsdaking
12

C'est une solution rapide au cas où vous voudriez convertir plus de colonnes de votre pandas.DataFramefloat en entier en considérant également le cas où vous pouvez avoir des valeurs 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 "")

J'ai essayé avec else x)et else None), mais le résultat a toujours le nombre flottant, donc je l'ai utilisé else "".

enri
la source
il appliquera le ""à toutes les valeurs danscol
Raheel
Il appliquera une chaîne vide ("") à toutes les valeurs manquantes, si c'est ce qui est requis, mais le reste des valeurs sera entier.
Krzysztof Słowiński
Merci pour cela. Cela a fonctionné lorsque .astype () et .apply (np.int64) ne l'ont pas fait.
Alison S
Cela semble hacky, et je ne vois aucune raison de l'utiliser sur les nombreuses alternatives disponibles.
AMC
8

En développant @Ryan G mentionné l'utilisation de la pandas.DataFrame.astype(<type>)méthode, on peut utiliser l' errors=ignoreargument pour convertir uniquement les colonnes qui ne produisent pas d'erreur, ce qui simplifie notamment la syntaxe. De toute évidence, la prudence doit être appliquée lors de l'ignorance des erreurs, mais pour cette tâche, il est très pratique.

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

À partir des documents pandas.DataFrame.astype :

erreurs: {'augmenter', 'ignorer'}, 'augmenter' par défaut

Contrôle la levée des exceptions sur les données non valides pour le type fourni.

  • augmenter: autoriser la levée des exceptions
  • ignorer: supprimer les exceptions. En cas d'erreur, renvoyer l'objet d'origine

Nouveau dans la version 0.20.0.

aebmad
la source
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
la source
5

Pour convertir toutes les colonnes flottantes en 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
la source
0

Voici une fonction simple qui descendra les flottants dans le plus petit type entier possible qui ne perdra aucune information. Pour des exemples,

  • 100,0 peut être converti de float en entier, mais 99,9 ne peut pas (sans perdre les informations à l'arrondi ou à la troncature)

  • De plus, 1.0 peut être abaissé jusqu'à la int8perte d'informations, mais le plus petit type entier pour 100_000.0 estint32

Exemples de code:

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
la source
0

Les colonnes qui doivent être converties en int peuvent être mentionnées dans un dictionnaire également comme ci-dessous

df = df.astype({'col1': 'int', 'col2': 'int', 'col3': 'int'})
prashanth
la source
-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
la source
1
astype(int)a déjà été mentionné à plusieurs reprises. Cette réponse n'ajoute rien de nouveau.
Georgy