何时在 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)?的主要内容,如果未能解决你的问题,请参考以下文章

GAE 标准 python 2.7 运行时何时消失?

在 Python 中,我如何知道一个进程何时完成?

何时在 python 中使用 type() 而不是 isinstanceof()? [复制]

何时在 Python 中选择 collections.Iterable 或 '__iter__' 属性? [复制]

何时在 Python 中使用哪些数组实现? [复制]

何时在 Python 中内联元类的定义?