Преобразование строковых объектов в int/float с помощью 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')

В файле csv "100 & life_180_data.csv" содержатся такие столбцы, как возраст, bmi, сигареты, Alocohol и т.д.

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

Сигаретная колонка содержит "Никогда" "1-5 Сигареты/день", "10-20 сигарет/день". Я хочу присвоить весу этим объектам (Никогда, 1-5 Cigarettes/day,....)

Ожидаемый вывод - это новый столбец CigarNum, который содержит только числа 0,1,2 CigarNum как ожидается до 8 строк, а затем показывает Nan до последнего ряда в столбце 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

Результат, который я получаю, не дает NaN после нескольких первых строк.

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

Ответы

Ответ 1

ОК, первая проблема заключается в том, что у вас есть встроенные пространства, из-за которых функция неправильно применяется:

исправить это с помощью векторизованного str:

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

теперь создайте новый столбец, который должен работать:

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

UPDATE

Благодаря @Jeff, как всегда, указывая на превосходные способы делать вещи:

Итак, вы можете вызвать replace вместо вызова apply:

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

вы также можете использовать метод factorize.

Размышление об этом, почему бы не просто установить значения dict в качестве плавающих в любом случае, а затем избежать преобразования типов?

Итак:

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

Версия 0.17.0 или новее

convert_objects устарел с 0.17.0, это было заменено на to_numeric

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

Здесь errors='coerce' будет возвращать NaN, где значения не могут быть преобразованы в числовое значение, без этого оно приведет к возникновению исключения

Ответ 2

Попробуйте использовать эту функцию для всех задач такого рода:

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)