2016-05-16 205 views
20

我试图筛选具有None作为行值PySpark数据帧:过滤Pyspark数据框列

df.select('dt_mvmt').distinct().collect() 

[Row(dt_mvmt=u'2016-03-27'), 
Row(dt_mvmt=u'2016-03-28'), 
Row(dt_mvmt=u'2016-03-29'), 
Row(dt_mvmt=None), 
Row(dt_mvmt=u'2016-03-30'), 
Row(dt_mvmt=u'2016-03-31')] 

,我可以用一个字符串值正确筛选:

df[df.dt_mvmt == '2016-03-31'] 
# some results here 

但这失败:

df[df.dt_mvmt == None].count() 
0 
df[df.dt_mvmt != None].count() 
0 

但是每个类别都有明确的值。这是怎么回事?

+0

据条目的条目[PEP 8](HTTPS ://www.python.org/dev/peps/pep-0008/#programming-recommendations)你应该使用is和'not'来比较None之类的单例。 – Natecat

+0

是的,但是没有用于筛选PySpark数据框的'is'或'is not': 'In [222]:df [df.dt_mvmt is None] .show() TypeError:'Column'object is callable' – Ivan

回答

38

您可以使用Column.isNull/Column.isNotNull

df.where(col("dt_mvmt").isNull()) 

df.where(col("dt_mvmt").isNotNull()) 

如果你想简单地丢弃NULL值,您可以使用na.dropsubset说法:

df.na.drop(subset=["dt_mvmt"]) 

NULL基于平等的比较将无法正常工作因为在SQL中NULL未定义,因此任何尝试将其与另一个值进行比较的操作都会返回NULL

sqlContext.sql("SELECT NULL = NULL").show() 
## +-------------+ 
## |(NULL = NULL)| 
## +-------------+ 
## |   null| 
## +-------------+ 


sqlContext.sql("SELECT NULL != NULL").show() 
## +-------------------+ 
## |(NOT (NULL = NULL))| 
## +-------------------+ 
## |    null| 
## +-------------------+ 

NULL比较值的唯一有效方法是IS/IS NOT这等同于isNull/isNotNull方法调用。

+2

太棒了,谢谢。我认为PySpark数据框中的这些过滤器会更加“pythonic”,但是,它们不是。我正在考虑向开发者询问这个问题。 – Ivan

+1

其实它是Pythonic。你不应该使用None来检查'__eq__';)'is'不会工作,因为它的行为方式不同。 – zero323

+0

奇怪这只适用于字符串列......看起来像'df.filter(“dt_mvmt不是NULL”)'处理两者。 –

9

尝试仅使用isNotNull函数。

df.filter(df.dt_mvmt.isNotNull()).count() 
+0

你摇滚!!!!!!! – logan

5

为了获得其在dt_mvmt列值不为空,我们有

df.filter("dt_mvmt is not NULL") 

和用于其是空我们有

df.filter("dt_mvmt is NULL")