【问题标题】:pd.NA vs np.nan for pandas熊猫的 pd.NA 与 np.nan
【发布时间】:2020-05-23 17:30:18
【问题描述】:

pd.NA vs np.nan 用于熊猫。哪一个与 pandas 一起使用,为什么要使用? pandas各自的主要优缺点是什么?

同时使用它们的一些示例代码:

import pandas as pd
import numpy as np

df = pd.DataFrame({ 'object': ['a', 'b', 'c',pd.NA],
                   'numeric': [1, 2, np.nan , 4],
                    'categorical': pd.Categorical(['d', np.nan,'f', 'g'])
                 })

输出:

|    | object   |   numeric | categorical   |
|---:|:---------|----------:|:--------------|
|  0 | a        |         1 | d             |
|  1 | b        |         2 | nan           |
|  2 | c        |       nan | f             |
|  3 | <NA>     |         4 | g             |

【问题讨论】:

  • 我很确定 pd.NA 在后端使用 np.nan。 Pandas 倾向于在后端大量使用 numpy
  • 这是什么版本的熊猫?
  • @roganjosh 我正在使用 Anaconda 的 v1.0.0。
  • "与 np.nan 相比,pd.NA 在某些运算中的行为不同。除了算术运算之外,pd.NA 在比较运算中也传播为“缺失”或“未知””来自here
  • @kenan 不,在这种情况下,它是distinct

标签: python pandas numpy dataframe


【解决方案1】:

pd.NA 是在最近发布的pandas-1.0.0 中引入的。

我建议在 np.nan 上使用它,因为它包含在 pandas 库中,它应该与 DataFrame 一起使用。

【讨论】:

  • 从您的链接看来,NA 现在是实验性功能,所以对于一些严重的事情,我认为现在应该避免使用它。
  • pd.NA 没有完全相同的功能,所以切换时要小心。 pd.NA 在相等操作中传播,np.nan 不传播。 pd.NA == 1 产生&lt;NA&gt;,但np.nan == 1 产生False
【解决方案2】:

根据docs

pd.NA 的目标是提供一个可以跨数据类型一致使用的“缺失”指标

因此,如果您的列具有多个 dtype,则使用 pd.NA 否则 np.nan 应该没问题。

但是,由于 pd.NA 似乎与 np.nan 具有相同的功能,因此最好将 pd.NA 用于所有 nan 目的

现在只有一个导入

【讨论】:

  • 从@tdpr 提供的pandas.pydata.org/pandas-docs/stable/whatsnew/v1.0.0.html 看来NA 现在是实验性功能,所以对于一些严重的事情我认为现在应该避免它。
  • pd.NA 没有完全相同的功能,所以切换时要小心。 pd.NA 在相等操作中传播,np.nan 不传播。 pd.NA == 1 产生&lt;NA&gt;,但np.nan == 1 产生False
【解决方案3】:

截至目前(pandas-1.0.0 发布)我真的建议谨慎使用它。

首先,它仍然是一个实验性功能:

实验性:pd.NA 的行为仍然可以在没有警告的情况下更改。

第二,行为不同于np.nan

np.nan 相比,pd.NA 在某些操作中的行为不同。除了算术运算,pd.NA 还在比较运算中作为“缺失”或“未知”传播。

来自release-notes的两个配额

为了展示一些额外的例子,我对插值行为感到惊讶:

创建简单的DataFrame:

df = pd.DataFrame({"a": [0, pd.NA, 2], "b": [0, np.nan, 2]})
df
#       a    b
# 0     0  0.0
# 1  <NA>  NaN
# 2     2  2.0

并尝试插值:

df.interpolate()
#       a    b
# 0     0  0.0
# 1  <NA>  1.0
# 2     2  2.0

这有一些原因(我仍在发现),无论如何,我只想强调这些差异 - 这是一个实验性功能,在某些情况下它的行为会有所不同

我认为这将是一个非常有用的功能,但我会非常小心“使用它而不是 np.nan”这样的陈述。在大多数情况下可能是这样,但在您不知道的情况下可能会引起一些麻烦。

【讨论】:

    【解决方案4】:

    pd.NA 和 np.nan 都表示数据框中的缺失值。
    我注意到的主要区别是 np.nan 是一个浮点值,而 pd.NA 存储一个整数值。 如果您的数据集中包含所有整数和一些缺失值的 column1,并且缺失值被 np.nan 替换,则该列的数据类型变为浮点数,因为 np.nan 是浮点数。 但是,如果您的数据集中包含所有整数和一些缺失值的 column2,并且缺失值被 pd.NA 替换,则该列的数据类型仍然是整数,因为 pd.NA 是整数。 如果您想将任何列保留为 int,而不是将其更改为 float,这可能会很有用。

    【讨论】:

      【解决方案5】:

      pd.NA 是镇上的新人,是熊猫自己的空值。很多数据类型都是从 numpy 借来的,包括 np.nan。

      从 pandas 1.0 开始,一个实验性的 pd.NA 值(单例)可用于表示标量缺失值。目前在nullable integerboolean和专用的string数据类型中作为缺失值指示符使用。

      pd.NA 的目标是提供一个“缺失”指示符,可以跨数据类型一致使用(而不是 np.nanNonepd.NaT,具体取决于数据类型)。

      让我们用所有不同的 dtypes 构建一个 df。

      d = {'int': pd.Series([1, None], dtype=np.dtype("O")),
          'float': pd.Series([3.0, np.NaN], dtype=np.dtype("float")),
          'str': pd.Series(['test', None], dtype=np.dtype("str")),
          "bool": pd.Series([True, np.nan], dtype=np.dtype("O")),
          "date": pd.Series(['1/1/2000', np.NaN], dtype=np.dtype("O"))}
      df1 = pd.DataFrame(data=d)
      
      df1['date'] = pd.to_datetime(df1['date'], errors='coerce')
      df1.info()
      df1
      
      

      输出

      <class 'pandas.core.frame.DataFrame'>
      RangeIndex: 2 entries, 0 to 1
      Data columns (total 5 columns):
       #   Column  Non-Null Count  Dtype         
      ---  ------  --------------  -----         
       0   int     1 non-null      object        
       1   float   1 non-null      float64       
       2   str     1 non-null      object        
       3   bool    1 non-null      object        
       4   date    1 non-null      datetime64[ns]
      dtypes: datetime64[ns](1), float64(1), object(3)
      memory usage: 208.0+ bytes
      
          int   float str     bool    date
      0   1     3.0   test    True    2000-01-01
      1   None  NaN   None    NaN     NaT
      
      

      如果您有一个使用传统类型的 DataFrame 或 Series,其中缺少使用 np.nan 表示的数据,则可以使用便捷方法 convert_dtypes() in Series 和 convert_dtypes() in DataFrame 将数据转换为使用较新的 dtypes 整数,字符串和布尔值以及从 v1.2 开始使用 convert_integer=False 浮动。

      df1[['int', 'str', 'bool', 'date']] = df1[['int', 'str', 'bool', 'date']].convert_dtypes()
      df1['float'] = df1['float'].convert_dtypes(convert_integer=False)
      df1.info()
      df1
      

      输出

      <class 'pandas.core.frame.DataFrame'>
      RangeIndex: 2 entries, 0 to 1
      Data columns (total 5 columns):
       #   Column  Non-Null Count  Dtype         
      ---  ------  --------------  -----         
       0   int     1 non-null      Int64         
       1   float   1 non-null      Float64       
       2   str     1 non-null      string        
       3   bool    1 non-null      boolean       
       4   date    1 non-null      datetime64[ns]
      dtypes: Float64(1), Int64(1), boolean(1), datetime64[ns](1), string(1)
      memory usage: 200.0 bytes
      
          int     float   str     bool    date
      0   1       3.0     test    True    2000-01-01
      1   <NA>    <NA>    <NA>    <NA>    NaT
      

      注意大写的“F”以区别np.float32np.float64,还要注意string 是新的pandas StringDtype(来自Pandas 1.0)而不是strobject。 还有pd.Int64(来自pandas 0.24)可为空的整数大写'I',而不是np.int64

      有关数据类型的更多信息,请阅读 herehere。这个页面有一些关于subtypes的好信息。

      我正在使用 pandas v1.2.4,因此希望我们能及时为所有数据类型提供一个通用的空值,这会温暖我们的心。

      警告这是新的,实验性使用现在要小心。

      【讨论】:

      • 谢谢,但老实说pd.NA 仍然让我有些困惑。您是否尝试过直接使用此 NA 值,例如对于您的第一列(int),如下所示:'int': pd.Series([1, pd.NA], dtype=np.dtype("O"))pd.NA 而不是None)?因为即使在使用convert_dtypes 方法之后,列类型也保持不变(object 而不是Int64)。
      • @Nerxis 目前,pd.NA 仅用于可为空的整数、布尔值和专用字符串数据类型。这里有一个关于使用对象的讨论github.com/pandas-dev/pandas/issues/32931
      • 是的,这个我明白,但我的意思是convert_dtypes不会把这列对象类型转换成Int64,这个应该支持。但是感谢您的链接,他们讨论了这个问题,包括 convert_dtypes 的函数,其中文档字符串有点混乱(与实际行为不同)。
      猜你喜欢
      • 2021-04-17
      • 2016-11-26
      • 1970-01-01
      • 2012-10-04
      • 2016-09-10
      • 2014-12-17
      • 2021-07-16
      • 2019-02-28
      • 1970-01-01
      相关资源
      最近更新 更多