在进行数据分析的时候,空值的处理是数据预处理过程中的重要环节。在利用pyspark进行数据空值填充的过程中,遇到了一个坑,坑得明明白白。就是简单的空值处理,花费了好几天的时间。其实还是API的理解不到位的原因。特此整理一下,共勉共享。
1. 问题描述
具体描述一下待处理的问题,以便记录整理。
假设有一个数据如下表:
id | name |
---|---|
1 | sun |
2 | wang |
3 | John |
4 |
注意,最后一个name为空。
需要解决这么几个问题:
- 将name字段进行空值填充;
- 添加一列并赋值为‘abc’
2. df.fillna() df.na.fill()
这两个函数其实是相同的,但是格外需要注意的是,要求替换内容与被替换的内容的数据格式必须一样,否则将被ignore!!!!!!!其实就是这个细节没有考虑到,才导致出错。
3. 第一个问题解决
from pyspark.sql.functions import lit
df = spark.createDataFrame([(1, "sun"),(2, "wang"), (3, "John"),(4,None)],["id", "name"])
df = df.na.fill('Unkown') #因为只有这一列为字符串
第二个问题解决
因为别的方面的需要,第二个问题分为了两步:
## 1. 添加一个空列
df = df.withColumn('newcol',lit(None)
## 一顿操作
## 2. 对该列中的空值进行填充
df.na.fill(subset='newcol',value='dsaf').show()
## 3. 甚至采用dict的形式,会报错!
df.na.fill({'newcol':'adfaf'}).show()
结果:
并没有替换成功!!!
报错信息:
Py4JJavaError: An error occurred while calling o821.fill.
: org.apache.spark.sql.AnalysisException: cannot resolve 'CAST('adfaf' AS NULL)' due to data type mismatch: cannot cast string to null;;
'Project [id#0L, name#1, coalesce(newcol#1027, cast(adfaf as null)) AS newcol#1065, nan#118, null#925]
结合报错信息,终于想到,是因为添加的这一列的数据类型可能不对。查看一下,果然:
df.dtypes
结果:
[('id', 'bigint'),
('name', 'string'),
('newcol', 'null'),
('nan', 'double'),
('null', 'string')]
原来是以为添加的这一列的数据格式为null,这就造成了格式不对应,被忽略了!!
所以解决方法就是在添加的时候,指定数据格式:
## 1. 添加一个空列
df = df.withColumn('newcol',lit(None).astype('int'))
这样,就没问题了!!!