熊猫的 pd.NA 与 np.nan

Posted

技术标签:

【中文标题】熊猫的 pd.NA 与 np.nan【英文标题】:pd.NA vs np.nan for pandas 【发布时间】: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 【参考方案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

有关数据类型的更多信息,请阅读 here 和 here。这个页面有一些关于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 的函数,其中文档字符串有点混乱(与实际行为不同)。

以上是关于熊猫的 pd.NA 与 np.nan的主要内容,如果未能解决你的问题,请参考以下文章

熊猫不识别 np.nan 值吗? [复制]

如何过滤 NaN(熊猫)?

如何根据上面的行删除行?蟒蛇熊猫

无法使用系列设置熊猫列值,而是将所有内容都设置为np.nan

熊猫:在每组中按平均值填充缺失值

熊猫:在每组中按平均值填充缺失值