2016-05-16 13 views
20

Próbuję filtrować dataframe PySpark który ma None jako wartość rzędu:Filtr kolumna Pyspark dataframe z Brak wartości

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')] 

i mogę filtrować poprawnie z wartości ciągu:

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

ale to się nie powiedzie:

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

Ale są zdecydowanie wartości w każdej kategorii. Co się dzieje?

+0

Zgodnie [PEP 8] (https : //www.python.org/dev/peps/pep-0008/#programming-recommendations) powinieneś używać 'is' i' is not' dla porównań do singletonów takich jak None. – Natecat

+0

Tak, ale nie ma "is" lub "nie jest" do filtrowania ramek danych PySpark: 'W [222]: df [df.dt_mvmt to Brak] .show() TypeError: Obiekt" Column "nie jest możliwy do wywołania' – Ivan

Odpowiedz

38

Można użyć Column.isNull/Column.isNotNull:

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

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

Jeśli chcesz po prostu upuścić NULL wartości można użyć na.drop z subset argumentu:

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

porównania Równość w oparciu o NULL nie będzie działać ponieważ w SQL NULL jest niezdefiniowany, więc każda próba porównania go z inną wartością zwraca NULL:

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


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

Jedyny poprawny sposób, aby porównać wartości z NULL jest IS/IS NOT które są równoważne isNull/isNotNull wywołań metod.

+2

Awesome, thanks. Myślałem, że te filtry na ramkach danych PySpark będą bardziej "pythonic", ale niestety, nie są. Zastanawiam się nad pytaniem o to deweloperów. – Ivan

+1

W rzeczywistości jest dość Pythonic. Nigdy nie powinieneś sprawdzać '__eq__' z None;) A' is' nie będzie działać, ponieważ nie zachowuje się w ten sam sposób. – zero323

+0

To dziwne, że działa tylko dla kolumn ciągów ... Wygląda na to, że 'df.filter (" dt_mvmt nie jest NULL ")' obsługuje oba. –

9

Spróbuj użyć funkcji isNotNull.

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

jesteś rock !!!!!!! – logan

5

Aby uzyskać dane, których wartości w kolumnie dt_mvmt nie tracą mamy

df.filter("dt_mvmt is not NULL") 

i do pozycji, które są puste mamy

df.filter("dt_mvmt is NULL")