2016-05-16 251 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")