这是Pandas的notnull()错误还是我理解上的误解(可能是误解)
我有一个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 个回答
我也遇到过这个问题。下面是我解决它的方法。“isnull()”是一个用来检查某个东西是否是NaN(不是一个数字)或者为空的函数。“~”这个符号是用来取反的,也就是说它会把后面的表达式变成相反的意思。所以我们是在说,从你原来的数据表中给我一个新的数据表,但只包含那些'数据'行不是空的部分。
df = df[~df['data'].isnull()]
希望这对你有帮助!