sql和pyspark是类似的
rddData = sc.parallelize( (Row(c="class1", s=50),
Row(c="class2", s=40),
Row(c="class3", s=None),
Row(c="class2", s=49),
Row(c="class3", s=29),
Row(c="class1", s=78)))
testDF = rddData.toDF()
testDF.show()
+------+----+
| c| s|
+------+----+
|class1| 50|
|class2| 40|
|class3|null|
|class2| 49|
|class3| 29|
|class1| 78|
+------+----+
如果sql或pyspark的isin()列表中含null, 则如果和除了None以外的值都匹配不上,是返回null。因为
sql和pyspark的逻辑都是,null不确定是什么东西,所以不能确定能否匹配。
testDF.select(fn.col('s').isin([20,40,None])).show()
+---------------------+
|(s IN (20, 40, NULL))|
+---------------------+
| null|
| true|
| null|
| null|
| null|
| null|
+---------------------+
如果sql或pyspark的原表中就为null,则它的isin()结果无论如何都是null,逻辑类似,不知道空值是什么,
所以也就不知道能不能和isin列表匹配。
testDF.select(fn.col('s').isin([2, 40])).show()
+--------------+
|(s IN (2, 40))|
+--------------+
| false|
| true|
| null|
| false|
| false|
| false|
+--------------+
但是在pandas里面就完全不是这样了。。。。
首先,pandas的dtype为数值型(如float,int)的列的空值始终是np.nan(即便None也会自动转成np.nan),不是null,pandas其实是把它作为浮点数看待
testDF.toPandas()
c s
0 class1 50.0
1 class2 40.0
2 class3 NaN
3 class2 49.0
4 class3 29.0
5 class1 78.0
testDF.toPandas()['s'].isnull()
0 False
1 False
2 True
3 False
4 False
5 False
Name: s, dtype: bool
所以,原表里的空值nan, 做了isin()判断后会认为浮点数nan不属于列表, 返回false
testDF.toPandas()['s'].isin([20, 40])
0 False
1 True
2 False
3 False
4 False
5 False
Name: s, dtype: bool
如果isin列表里面含空值none或np.nan,会认为浮点数nan与这个列表里面的none(nan)相等(刚才讲过了,对于dtype为数值型的列,none会被转成浮点数np.nan),返回true。
testDF.toPandas()['s'].isin([20, 40, None])
0 False
1 True
2 True
3 False
4 False
5 False
Name: s, dtype: bool
但是如果某列的类型是object就不是这样了,None和np.nan是不一样的。补充说明一点的是,pandas里面不管一列的dtype是什么,np.nan=np.nan或者np.nan=None的逻辑判断都会得到false,而且pandas groupby永远是会排除空值的(spark会把null单独作为一组)。离开了pandas, 你直接用np.nan in [2,3,np.nan]会得到true, 但是np.nan in [2,3,None]得到false,因为在pandas里面数值型的列会把None自动转成了np.nan而已
df = pd.DataFrame({'ss': [np.nan, 1, None], 'dd':[None, 'd', np.nan]})
ss dd
0 NaN None
1 1.0 d
2 NaN NaN
df['dd'].isin([np.nan])
0 False
1 False
2 True
Name: dd, dtype: bool
df['dd'].isin([None])
0 True
1 False
2 False
Name: dd, dtype: bool