对于python语言中,在pandas 和 pyspark以及普通的python代码中经常遇到空值需要处理的情况,有时见到的是None,有时是null,有时是NaN,本文尝试对这三者进行一个汇总,和对于pyspark中关于空值的处理进行汇总。
目录
二、缺失值填充-dataframe.fillna函数 和 dataframe.na.fill函数
一 、含义区分:
None 和null
在python代码中并没有直接的的null,但是有和其意义相近的None。对于当None值被写入在python相关的pandas 和pyspark 的dataframe中时,其表示便是null 。
None
表示空值,它是一个特殊 Python 对象, None的类型是NoneType
。None
是 NoneType 数据类型的唯一值,我们不能再创建其它 NoneType 类型的变量,但是可以将 None 赋值给任何变量。
print(type(None))
# 输出 <class 'NoneType'>
在spark中,定义df时的输入为none,进入df后的表示便是null。
df = spark.createDataFrame([(None, 2.0),(1.0,3.0)], ("a", "b"))
df.show()
输出:
+----+---+ | a| b| +----+---+ |null|2.0| | 1.0|3.0| +----+---+
另外: 对于所有没有 return 语句的函数定义,Python 都会在末尾加上 return None,使用不带值的 return 语句(也就是只有 return 关键字本身),那么就返回 None。
NaN
NaN本身是浮点数的空值。 当使用Numpy或者Pandas处理数据的时候,经常会遇到条目中没有数据,然后当我们在去打印的时候就会出现NaN。
import numpy as np
print(type(np.nan))
输出: <class 'float'>
注意: 和任何值做计算的结果都是NaN
如: print(np.nan+20.5 ) ,不会报错,但是结果为nan
在pyspark 的dataframe中也可以用float('nan') 去给相关字段值,此时得到的值并不能被isnull识别,必须要调用 isnan
两者在pyspark中的对比联系案例
# 两种类型的空值,一种是普通的缺失值,另一种是在数值型字段中有时专门指定的'nan’值。普通的缺失值,在建df时可以用None指定。
df = spark.createDataFrame([ (None, 2.0),(1.0, float('nan'))], ("a", "b"))
df.show()
+----+---+
| a| b|
+----+---+
|null|2.0|
| 1.0|NaN|
+----+---+
from pyspark.sql.functions import isnull,isnan
print(df.select(isnull('a').alias('r1')).show()) # 对于a列定义时的None已经转换为Null
print(df.select(isnan('a').alias('r1')).show()) # None并不能被isnan识别
print(df.filter(df.b.isNull()|df.a.isNull()).show())# b这列的NaN并不能被isnull识别,nan并不会认为是null,
输出:
+-----+ | r1| +-----+ | true| |false| +-----+ +-----+ | r1| +-----+ |false| |false| +-----+ +----+---+ | a| b| +----+---+ |null|2.0| +----+---+
二、缺失值填充-dataframe.fillna函数 和 dataframe.na.fill函数
spark dataframe 的 fillna 函数等同于 .na.fill(),.na.fill 函数底层也是调用 fillna,它的作用是填充列值 null 为指定的值,对于Nan 和None 都可以进行填充。替换的列可以指定,每列的替换规则也可以通过 dict 字典参数设置.
fillna(self, value, subset=None) ,另一个别名函数 na.fill() 函数,该函数是版本 1.3.1 开始新增的。
-
参数 value 支持 2 大形式:
第一种形式是接收 int, long, float, string, bool 固定值设置,这种一般和后面的 subset 参数一起使用,将指定的字段统一改为指定值。
第二种形式是 dict 字典类型,设置具体字段或列的值映射,这种形式会忽略后面的 subset 参数设置,因为后面的字段指定无意义。
-
subset 参数是可选项,指定要填充的字段或列列表,和 value 参数的第一种形式搭配使用。如果不设置,则表示作用于所有字段;如果设置的字段类型与设置值的类型不匹配,该字段值的替换则忽略,即不生效。
df.fillna({'a':20,'b':40}).show() ## 对于Nan 和None 都进行了填充,说明.fillna对于NaN和None(null)都能识别。
结果:
+----+----+ | a| b| +----+----+ |20.0| 2.0| | 1.0|40.0| +----+----+
三、含有空值的过滤
对于None或者Null ,两种方式,一种使用标准ANSI-SQL SQL表达式来过滤列得到函空值的对应的行 ,另一种使用column自带的.BooleanType列对象
## 方式1 使用标准ANSI-SQL SQL表达式来过滤列
print(df.where('a is null ').show())
print(df.filter('a is null').show())
## 方式2 使用type.BooleanType列对象来过滤
print(df.where(df['a'].isNull()).show())
结果都是:
+----+---+ | a| b| +----+---+ |null|2.0| +----+---+
注意: 对于缺失值Nan, pyspark的dataframe中并没有 isNaN,
print(df.where(df['b'].isNaN()).show())## 此处报错
# 对于pyspark的dataframe 里,column有isNull但是没有isNan的判断。isNan 要借助pyspark.functions里的nan
from pyspark.sql.functions import isnull,isnan
df = spark.createDataFrame([ (None, 2.0),(1.0, float('nan'))], ("a", "b"))
print(df[isnan('b').alias('rb')].show()) # isnan可以识别出来。
输出:
+---+---+ | a| b| +---+---+ |1.0|NaN| +---+---+
如果觉得本文对你有所帮助,还请帮忙点个赞或者收藏,非常感谢!
参考: