我有一个非常脏的csv,其中有几列只有空值。
我想删除它们。我试图选择所有列中的空值计数不等于行数的所有列。
clean_df = bucketed_df.select([c for c in bucketed_df.columns if count(when(isnull(c), c)) not bucketed_df.count()])
但是,出现此错误:
SyntaxError: invalid syntax
File "<command-2213215314329625>", line 1
clean_df = bucketed_df.select([c for c in bucketed_df.columns if count(when(isnull(c), c)) not bucketed_df.count()])
^
SyntaxError: invalid syntax
如果有人可以帮助我摆脱这些肮脏的专栏,那就太好了。
答案 0 :(得分:0)
有两种方法可以解决此问题,
1)编写UDF函数以添加一个列,如果所需列(您正在检查NULL的列)的值为NULL,则该列的值为1,然后对列求和,如果总和等于到行数,然后删除列
2)使用amazon spark dq库(spark的开源数据质量库),该库具有用于配置数据的功能,dq返回的列之一是每一列的完整性因子,如果完整性因子为1,则整个列的值为NULL,您可以删除这些列 我个人认为此选项很棒,因为它旨在使用spark进行数据质量检查
下面的链接中有很多示例
https://aws.amazon.com/blogs/big-data/test-data-quality-at-scale-with-deequ/ https://github.com/awslabs/deequ
答案 1 :(得分:0)
可以使用函数“ min”,并且可以删除具有空值的列。在Scala上,可以轻松将其翻译成Python:
// data sample
val df = Seq(("Bug", null.asInstanceOf[Integer], null.asInstanceOf[String]),
("Termit", null.asInstanceOf[Integer], null.asInstanceOf[String]))
.toDF("name", "size", "type")
val fieldNames = df.schema.fieldNames
// get null values
val fieldExpressions = fieldNames.map(c => min(c).alias(c))
val firstRow = df.select(fieldExpressions: _*).collect().head
val fieldsToDrop = fieldNames.filter(f => firstRow.isNullAt(fieldNames.indexOf(f)))
答案 2 :(得分:0)
我对pyspark的经验很少,但是用counts创建一个数据帧并将其转换为pandas
可能不是一个坏主意,因为counts数据帧只有一行:
从如下所示的数据帧开始,并另存为null_df
+---+---+---+----+
| A| B| C| D|
+---+---+---+----+
| 1| a| b|null|
| 2| c| d|null|
| 3| e| f|null|
+---+---+---+----+
import pyspark.sql.functions as F
counts = null_df.select([F.count(i).alias(i) for i in null_df.columns]).toPandas()
output = null_df.select(*counts.columns[counts.ne(0).iloc[0]])
或者甚至将整个第一行都转换成字典,然后遍历字典
counts1 = null_df.select([F.count(i).alias(i) for i in null_df.columns])
output2 = null_df.select([k for k,v in counts1.first().asDict().items() if v >0])
显示以下内容:
+---+---+---+
| A| B| C|
+---+---+---+
| 1| a| b|
| 2| c| d|
| 3| e| f|
+---+---+---+
在我的系统中测试过的基准:
%%timeit
counts = null_df.select([F.count(i).alias(i) for i in null_df.columns]).toPandas()
output = null_df.select(*counts.columns[counts.ne(0).iloc[0]])
#8.73 s ± 412 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
counts1 = null_df.select([F.count(i).alias(i) for i in null_df.columns])
output2 = null_df.select([k for k,v in counts1.first().asDict().items() if v >0])
#9.43 s ± 253 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
%%timeit
counts1 = null_df.select([F.count(i).alias(i) for i in null_df.columns])
output1 = null_df.select([c for c in counts1.columns if counts1[[c]].first()[c] > 0])
#35.3 s ± 1 s per loop (mean ± std. dev. of 7 runs, 1 loop each)