sql里面的in和notin

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

发布了31 篇原创文章 · 获赞 18 · 访问量 6028

猜你喜欢

转载自blog.csdn.net/weixin_40027284/article/details/103388158
今日推荐