web-dev-qa-db-fra.com

Conversion d'objets chaîne en int / float en utilisant pandas

import pandas as pd

path1 = "/home/supertramp/Desktop/100&life_180_data.csv"

mydf =  pd.read_csv(path1)

numcigar = {"Never":0 ,"1-5 Cigarettes/day" :1,"10-20 Cigarettes/day":4}

print mydf['Cigarettes']

mydf['CigarNum'] = mydf['Cigarettes'].apply(numcigar.get).astype(float)

print mydf['CigarNum']

mydf.to_csv('/home/supertramp/Desktop/powerRangers.csv')

Le fichier csv "100 & life_180_data.csv" contient des colonnes comme age, bmi, Cigarettes, Alocohol etc.

No                int64
Age               int64
BMI             float64
Alcohol          object
Cigarettes       object
dtype: object

La colonne Cigarettes contient "Jamais" "1-5 cigarettes/jour", "10-20 cigarettes/jour". Je veux attribuer des poids à ces objets (Jamais, 1-5 cigarettes/jour, ....)

La sortie attendue est la nouvelle colonne CigarNum ajoutée qui ne comprend que les chiffres 0,1,2 CigarNum est comme prévu jusqu'à 8 lignes, puis affiche Nan jusqu'à la dernière ligne dans la colonne CigarNum

0                     Never
1                     Never
2        1-5 Cigarettes/day
3                     Never
4                     Never
5                     Never
6                     Never
7                     Never
8                     Never
9                     Never
10                    Never
11                    Never
12     10-20 Cigarettes/day
13       1-5 Cigarettes/day
14                    Never
...
167                    Never
168                    Never
169     10-20 Cigarettes/day
170                    Never
171                    Never
172                    Never
173                    Never
174                    Never
175                    Never
176                    Never
177                    Never
178                    Never
179                    Never
180                    Never
181                    Never
Name: Cigarettes, Length: 182, dtype: object

La sortie que j'obtiens ne devrait pas donner NaN après quelques premières lignes.

0      0
1      0
2      1
3      0
4      0
5      0
6      0
7      0
8      0
9      0
10   NaN
11   NaN
12   NaN
13   NaN
14     0
...
167   NaN
168   NaN
169   NaN
170   NaN
171   NaN
172   NaN
173   NaN
174   NaN
175   NaN
176   NaN
177   NaN
178   NaN
179   NaN
180   NaN
181   NaN
Name: CigarNum, Length: 182, dtype: float64
21
cruxer

OK, le premier problème est que vous avez des espaces incorporés provoquant une application incorrecte de la fonction:

résoudre ce problème en utilisant str vectorisé:

mydf['Cigarettes'] = mydf['Cigarettes'].str.replace(' ', '')

maintenant, créez votre nouvelle colonne devrait juste fonctionner:

mydf['CigarNum'] = mydf['Cigarettes'].apply(numcigar.get).astype(float)

[~ # ~] mise à jour [~ # ~]

Merci à @Jeff comme toujours d'avoir indiqué des façons de faire supérieures:

Vous pouvez donc appeler replace au lieu d'appeler apply:

mydf['CigarNum'] = mydf['Cigarettes'].replace(numcigar)
# now convert the types
mydf['CigarNum'] = mydf['CigarNum'].convert_objects(convert_numeric=True)

vous pouvez également utiliser la méthode factorize également.

En y réfléchissant, pourquoi ne pas simplement définir les valeurs dict pour qu'elles soient flottantes de toute façon et ensuite vous évitez la conversion de type?

Alors:

numcigar = {"Never":0.0 ,"1-5 Cigarettes/day" :1.0,"10-20 Cigarettes/day":4.0}

Version 0.17.0 ou plus récente

convert_objects est déconseillé depuis 0.17.0, il a été remplacé par to_numeric

mydf['CigarNum'] = pd.to_numeric(mydf['CigarNum'], errors='coerce')

Ici errors='coerce' renverra NaN où les valeurs ne peuvent pas être converties en une valeur numérique, sans cela, il déclenchera une exception

33
EdChum

Essayez d'utiliser cette fonction pour tous les problèmes de ce type:

def get_series_ids(x):
    '''Function returns a pandas series consisting of ids, 
       corresponding to objects in input pandas series x
       Example: 
       get_series_ids(pd.Series(['a','a','b','b','c'])) 
       returns Series([0,0,1,1,2], dtype=int)'''

    values = np.unique(x)
    values2nums = dict(Zip(values,range(len(values))))
    return x.replace(values2nums)
4
Apogentus