这是Pandas的notnull()错误还是我理解上的误解(可能是误解)

4 投票
1 回答
6746 浏览
提问于 2025-04-18 07:13

我有一个pandas数据框,里面有两列,默认的索引方式。第一列是字符串,第二列是日期。最上面的日期是NaN(其实应该是NaT)。

index    somestr    date
0        ON         NaN
1        1C         2014-06-11 00:00:00
2        2C         2014-07-09 00:00:00
3        3C         2014-08-13 00:00:00
4        4C         2014-09-10 00:00:00
5        5C         2014-10-08 00:00:00
6        6C         2014-11-12 00:00:00
7        7C         2014-12-10 00:00:00
8        8C         2015-01-14 00:00:00
9        9C         2015-02-11 00:00:00
10       10C        2015-03-11 00:00:00
11       11C        2015-04-08 00:00:00
12       12C        2015-05-13 00:00:00

我们把这个数据框叫做df。

当我运行:

df[pd.notnull(df['date'])]

我希望第一行能消失,但它没有。

如果我通过设置来删除字符串那一列:

df=df[['date']]

然后再应用:

df[pd.notnull(df['date'])]

那么第一行的空值就会消失。

另外,如果所有的列都是数字或日期类型,带空值的行总是会消失。但只要有字符串类型的列,这个问题就会出现。

这肯定是个bug,对吧?我不确定其他人能否复现这个问题。

这是在我的Enthought Canopy for Windows上(我对UNIX/Linux的命令行不太懂)。

根据Jeff和unutbu的要求:

@ubuntu -
df.dtypes
somestr    object
date       object
dtype:  object

还有:

type(df.iloc[0]['date'])
pandas.tslib.NaTType

在代码中,这一列被特别指定为pd.NaT。我也不明白为什么它显示NaN,而不是NaT。当我使用这个简单的数据框时,过滤是正常的:

df=pd.DataFrame({'somestr' : ['aa', 'bb'], 'date' : [pd.NaT, dt.datetime(2014,4,15)]}, columns=['somestr', 'date'])

还要注意,虽然上面的表格输出了NaN,但下面的输出是NaT:

df['date'][0]
NaT

还有:

pd.notnull(df['date'][0])
False

pd.notnull(df['date'][1])
True

但是……在评估数组时,它们都返回了True——真是奇怪……

np.all(pd.notnull(df['date']))
True

@Jeff - 这是0.12版本。我被这个问题困住了。这个数据框是通过连接两个不同的数据框创建的,这两个数据框是通过psql从数据库查询中获取的。日期和一些其他浮点列是通过我做的计算添加的。当然,我过滤了两个相关的列,直到我发现字符串类型的列导致了问题。

************ 如何复现 **********

import pandas as pd
import datetime as dt

print(pd.__version__)
# 0.12.0

df = pd.DataFrame({'somestr': ['aa', 'bb'], 'date': ['cc', 'dd']},
                  columns=['somestr', 'date'])
df['date'].iloc[0] = pd.NaT
df['date'].iloc[1] = pd.to_datetime(dt.datetime(2014, 4, 15))
print(df[pd.notnull(df['date'])])
#   somestr                 date
# 0      aa                  NaN
# 1      bb  2014-04-15 00:00:00

df2 = df[['date']]
print(df2[pd.notnull(df2['date'])])
#                  date
# 1 2014-04-15 00:00:00

所以,这个数据框最初是所有字符串条目——然后日期列被转换为日期,最上面是NaT——注意在表格中是NaN,但当使用df.iloc[0]['date']时,你确实能看到NaT。使用上面的代码片段,你会发现根据非空值进行过滤时,带或不带somestr列的结果都很奇怪。再次强调——这是在Enthought Canopy for Windows上,使用的是Pandas 0.12和NumPy 1.8。

1 个回答

2

我也遇到过这个问题。下面是我解决它的方法。“isnull()”是一个用来检查某个东西是否是NaN(不是一个数字)或者为空的函数。“~”这个符号是用来取反的,也就是说它会把后面的表达式变成相反的意思。所以我们是在说,从你原来的数据表中给我一个新的数据表,但只包含那些'数据'行不是空的部分。

df = df[~df['data'].isnull()]

希望这对你有帮助!

撰写回答