使用pandas将字符串对象转换为整数/浮点数

24
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,香烟,酒精等。

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

香烟栏包含“从不”、“1-5支每天”、“10-20支每天”的内容。 我想给这些对象(从不,1-5支每天,...)分配权重。

预期的输出是添加了一个新列CigarNum,其中只包含数字0、1、2 CigarNum预计在前8行中显示,并在CigarNum列中的最后一行之前显示Nan。


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

你确定第10行和第11行实际上等于“Never”,并且值中没有空格或其他字符吗? - EdChum
是的,我到现在还没有检查空格。非常感谢。你能帮我找一个忽略这些空格的高效方法吗?我有很多列开头都有空格。提前致谢。 - codex
2个回答

36

好的,首先问题在于您有嵌入空格导致函数应用不正确:

使用矢量化的 str 来解决这个问题:

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

现在创建新列应该可以正常工作:

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

更新

感谢一如既往的 Jeff 指出更好的做事方式:

因此,你可以调用 replace 而不是调用 apply

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

你也可以使用 factorize 方法。

思考一下,为什么不直接将字典的值设置为浮点数,这样就避免了类型转换呢?

因此:

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

版本 0.17.0 或更新版本

convert_objects0.17.0 起已被弃用,现已被 to_numeric 替代。

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

这里的errors='coerce'将会在数值无法转换时返回NaN,如果没有这个参数则会抛出异常。

errors='coerce'将不能转换成数值的值替换为NaN


1
你可以使用series.replace(dict)来进行替换,然后使用convert_objects(convert_numeric=True)将其强制转换为浮点数;你也可以使用factorize来创建分类变量(例如,将字符串映射到数字)。 - Jeff
@Jeff,那现在replace比调用mapapply并传递字典更快吗?我不知道还有factorize,这是什么时候引入的? - EdChum
替换应该更快;“因式分解”已经存在一段时间了(但没有宣传:) - Jeff
@EdChum 你好,当我这样做时,会出现“正在尝试在Dataframe的副本切片上设置值”的错误提示,我该如何更改原始数据框? - haneulkim
@h_musk 请参见https://dev59.com/8WIj5IYBdhLWcg3wHhlX 基本上,如果您想对副本进行操作,则应调用df.copy(),否则,请遵循该链接,如果您想要对视图进行操作。 - EdChum

4

尝试使用此函数解决所有类似问题:

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)

1
很好!小注释:需要_import numpy as np_;期望的附加功能:如果出现空值,可以选择将其分配为-1或类似的值。 - Denis

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接