何时在 python 中应用(pd.to_numeric)和何时 astype(np.float64)?
Posted
技术标签:
【中文标题】何时在 python 中应用(pd.to_numeric)和何时 astype(np.float64)?【英文标题】:When to apply(pd.to_numeric) and when to astype(np.float64) in python? 【发布时间】:2017-02-26 23:42:19 【问题描述】:我有一个名为 xiv
的 pandas DataFrame 对象,其中有一列 int64
体积测量值。
In[]: xiv['Volume'].head(5)
Out[]:
0 252000
1 484000
2 62000
3 168000
4 232000
Name: Volume, dtype: int64
我已阅读其他建议以下解决方案的帖子(如 this 和 this)。但是当我使用任何一种方法时,它似乎都不会改变基础数据的dtype
:
In[]: xiv['Volume'] = pd.to_numeric(xiv['Volume'])
In[]: xiv['Volume'].dtypes
Out[]:
dtype('int64')
或者……
In[]: xiv['Volume'] = pd.to_numeric(xiv['Volume'])
Out[]: ###omitted for brevity###
In[]: xiv['Volume'].dtypes
Out[]:
dtype('int64')
In[]: xiv['Volume'] = xiv['Volume'].apply(pd.to_numeric)
In[]: xiv['Volume'].dtypes
Out[]:
dtype('int64')
我还尝试制作一个单独的 pandas Series
并使用上面在该系列中列出的方法并重新分配给 x['Volume']
对象,这是一个 pandas.core.series.Series
对象。
不过,我找到了使用 numpy
包的 float64
类型解决此问题的方法 - 这可行,但我不知道为什么不同 .
In[]: xiv['Volume'] = xiv['Volume'].astype(np.float64)
In[]: xiv['Volume'].dtypes
Out[]:
dtype('float64')
有人可以解释如何使用pandas
库完成numpy
库似乎可以通过其float64
类轻松完成的工作吗?也就是将xiv
DataFrame 中的列原位转换为float64
。
【问题讨论】:
int64
已经是“数字”dtype。 to_numeric()
应该有助于将字符串转换为数字 dtypes...
引用的帖子显示调用to_numeric
返回的dtype
将是float64
...
检查这个:pd.to_numeric(pd.Series(['1','2','3'])).dtype
。仅在必要时才使用 float64: 1. 系列中存在 NaN 或不可转换的值。 2.系列中有花车
什么是“问题”以及您的目标是什么? BTW pd.Series.astype(np.float64) - 是 Pandas 方法
我已经添加了一些演示 - 我希望它现在变得更清晰了......
【参考方案1】:
如果您已经有数字 dtype (int8|16|32|64
,float64
,boolean
),您可以使用 Pandas .astype() 方法将其转换为另一种“数字”dtype。
演示:
In [90]: df = pd.DataFrame(np.random.randint(10**5,10**7,(5,3)),columns=list('abc'), dtype=np.int64)
In [91]: df
Out[91]:
a b c
0 9059440 9590567 2076918
1 5861102 4566089 1947323
2 6636568 162770 2487991
3 6794572 5236903 5628779
4 470121 4044395 4546794
In [92]: df.dtypes
Out[92]:
a int64
b int64
c int64
dtype: object
In [93]: df['a'] = df['a'].astype(float)
In [94]: df.dtypes
Out[94]:
a float64
b int64
c int64
dtype: object
它不适用于object
(字符串)dtypes,不能转换为数字:
In [95]: df.loc[1, 'b'] = 'XXXXXX'
In [96]: df
Out[96]:
a b c
0 9059440.0 9590567 2076918
1 5861102.0 XXXXXX 1947323
2 6636568.0 162770 2487991
3 6794572.0 5236903 5628779
4 470121.0 4044395 4546794
In [97]: df.dtypes
Out[97]:
a float64
b object
c int64
dtype: object
In [98]: df['b'].astype(float)
...
skipped
...
ValueError: could not convert string to float: 'XXXXXX'
所以这里我们要使用pd.to_numeric()方法:
In [99]: df['b'] = pd.to_numeric(df['b'], errors='coerce')
In [100]: df
Out[100]:
a b c
0 9059440.0 9590567.0 2076918
1 5861102.0 NaN 1947323
2 6636568.0 162770.0 2487991
3 6794572.0 5236903.0 5628779
4 470121.0 4044395.0 4546794
In [101]: df.dtypes
Out[101]:
a float64
b float64
c int64
dtype: object
【讨论】:
只是一个问题,你为什么写 df.b,而不是 df['b']? @SalmanALharbi:使用这种格式 df['column name'] 的列总是更好,但有时如果列名没有空格,您可以直接使用列名作为 df.columnname 但 df['列名'] 应始终使用 @OnlySalman 这只是一种不同且有效的语法。有些人更喜欢 df['column_name] 而其他人更喜欢 df.column_name。使用 df.column_name 列名必须是有效的 Python 语法。例如:如果列名以数字开头,则不能使用点表示法。你不能做 df.1,你必须做 df[1]【参考方案2】:对此我没有技术解释,但是我注意到 pd.to_numeric() 在转换字符串 'nan' 时会引发以下错误:
In [10]: df = pd.DataFrame('value': 'nan', index=[0])
In [11]: pd.to_numeric(df.value)
Traceback (most recent call last):
File "<ipython-input-11-98729d13e45c>", line 1, in <module>
pd.to_numeric(df.value)
File "C:\Users\joshua.lee\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\tools\numeric.py", line 133, in to_numeric
coerce_numeric=coerce_numeric)
File "pandas/_libs/src\inference.pyx", line 1185, in pandas._libs.lib.maybe_convert_numeric
ValueError: Unable to parse string "nan" at position 0
而 astype(float) 没有:
df.value.astype(float)
Out[12]:
0 NaN
Name: value, dtype: float64
【讨论】:
【参考方案3】:我观察到我能够先将 object(str) 转换为 float,然后再转换为 Int64。
df = pd.DataFrame(np.random.randint(10**5,10**7,(5,3)),columns=list('abc'),
dtype=np.int64)
df['a'] = df['a'].astype('str')
df.dtypes
df['a'] = df['a'].astype('float')
df['a'] = df['a'].astype('int64')
工作正常。
【讨论】:
【参考方案4】:你可以用这个:
pd.to_numeric(df.value, errors='coerce').fillna(0, downcast='infer')
它将用零代替nan。
【讨论】:
【参考方案5】:我想我有一个支持其他人给出的解释。总之,正如我将在下面展示的那样,pd.to_numeric(arg, errors='coerce')
可以处理无法转换为数字的数字,例如 '50a'
通过将它们转换为 NaN。然后,您可以删除空值。而DataFrame.astype()
没有这种能力。
在实践中,我首先使用pd.to_numeric(arg, errors='coerce')
,尤其是当 DataFrame 列或系列有可能保存无法转换为数字的数字时,因为它将这些数字转换为 NaN,然后如果需要,我会删除 NaN,然后使用DataFrame.astype()
将数据类型转换为我想要的确切数字数据类型,例如 float64、int32、int64 等。
See examples below:
bio = 'Age': [56, 57, '50a'], 'Name': ['YOU', 'ME', 'HIM']
df = pd.DataFrame(bio)
>>> df
Age Name
0 56 YOU
1 57 ME
2 50a HIM
>>> df['Age'] = df['Age'].astype(int)
.......
.......
ValueError: invalid literal for int() with base 10: '50a'
# Even when the error is forced to be ignore, the change is not made
>>> df['Age'] = df['Age'].astype(int, errors='ignore')
>>> df
Age Name
0 56 YOU
1 57 ME
2 50a HIM
观察当我使用pd.to_numeric(arg, errors='coerce')
时会发生什么
>>> df['Age'] = pd.to_numeric(df['Age']) #Used without the coerce
........
........
ValueError: Unable to parse string "50a" at position 2
# When used with parameter: error = coerce, it changes invalid values to Nan.
# You can then use astype(int) or astype(float) to convert the NaN to 0
>>> df['Age'] = pd.to_numeric(df['Age'], errors='coerce')
>>> df
Age Name
0 56.0 YOU
1 57.0 ME
2 NaN HIM
# You can then drop nulls if you desire
总而言之,两者都针对特定目的携手合作,尤其是在处理空值时
【讨论】:
以上是关于何时在 python 中应用(pd.to_numeric)和何时 astype(np.float64)?的主要内容,如果未能解决你的问题,请参考以下文章
何时在 python 中使用 type() 而不是 isinstanceof()? [复制]