我想对我的数据进行一些预处理,并且我想删除稀疏的行(对于某个阈值)。
例如,我有一个包含10个功能的数据帧表,并且我有一个8位空值的行,然后我想删除它。
我找到了一些相关主题,但我找不到任何有用的信息。
stackoverflow.com/questions/3473778/count-number-of-nulls-in-a-row
上面链接中的示例对我来说不起作用,因为我想自动执行此预处理。我不能写列名并做相应的事情。
那么无论如何在没有使用带有scala的Apache Spark中的列名来执行此删除操作?
答案 0 :(得分:3)
考试日期:
case class Document( a: String, b: String, c: String)
val df = sc.parallelize(Seq(new Document(null, null, null), new Document("a", null, null), new Document("a", "b", null), new Document("a", "b", "c"), new Document(null, null, "c"))).df
使用UDF
通过以下David和我的RDD版本重新混合答案,您可以使用占用一行的UDF来完成:
def nullFilter = udf((x:Row) => {Range(0, x.length).count(x.isNullAt(_)) < 2})
df.filter(nullFilter(struct(df.columns.map(df(_)) : _*))).show
使用RDD
您可以将其转换为Row中列的rdd循环,并计算有多少为null。
sqlContext.createDataFrame(df.rdd.filter( x=> Range(0, x.length).count(x.isNullAt(_)) < 2 ), df.schema).show
答案 1 :(得分:2)
使用UDF更清洁:
import org.apache.spark.sql.functions.udf
def countNulls = udf((v: Any) => if (v == null) 1; else 0;))
df.registerTempTable("foo")
sqlContext.sql(
"select " + df.columns.mkString(", ") + ", " + df.columns.map(c => {
"countNulls(" + c + ")"
}).mkString(" + ") + "as nullCount from foo"
).filter($"nullCount" > 8).show
如果使查询字符串让您感到紧张,那么您可以试试这个:
var countCol: org.apache.spark.sql.Column = null
df.columns.foreach(c => {
if (countCol == null) countCol = countNulls(col(c))
else countCol = countCol + countNulls(col(c))
});
df.select(Seq(countCol as "nullCount") ++ df.columns.map(c => col(c)):_*)
.filter($"nullCount" > 8)
答案 2 :(得分:2)
我很惊讶没有答案指出Spark SQL只有很少的标准功能符合要求:
例如,我有一个包含10个功能的数据帧表,并且我有一个8位空值的行,然后我想删除它。
你可以使用DataFrameNaFunctions.drop方法的一种变体,minNonNulls
设置得恰当,比如2。
drop(minNonNulls:Int,cols:Seq [String]):DataFrame 返回一个新的DataFrame,它删除指定列中包含少于minNonNulls非空和非NaN值的行。 / p>
并且要满足要求中列名的可变性:
我不能写列名并做相应的事情。
您只需使用Dataset.columns:
即可columns:Array [String] 以数组形式返回所有列名。
假设您拥有以下数据集,其中包含5个要素(列)和几乎所有null
的几行。
val ns: String = null
val features = Seq(("0","1","2",ns,ns), (ns, ns, ns, ns, ns), (ns, "1", ns, "2", ns)).toDF
scala> features.show
+----+----+----+----+----+
| _1| _2| _3| _4| _5|
+----+----+----+----+----+
| 0| 1| 2|null|null|
|null|null|null|null|null|
|null| 1|null| 2|null|
+----+----+----+----+----+
// drop rows with more than (5 columns - 2) = 3 nulls
scala> features.na.drop(2, features.columns).show
+----+---+----+----+----+
| _1| _2| _3| _4| _5|
+----+---+----+----+----+
| 0| 1| 2|null|null|
|null| 1|null| 2|null|
+----+---+----+----+----+
答案 3 :(得分:1)
以下是Spark 2.0的替代方案:
val df = Seq((null,"A"),(null,"B"),("1","C"))
.toDF("foo","bar")
.withColumn("foo", 'foo.cast("Int"))
df.show()
+----+---+
| foo|bar|
+----+---+
|null| A|
|null| B|
| 1| C|
+----+---+
df.where('foo.isNull).groupBy('foo).count().show()
+----+-----+
| foo|count|
+----+-----+
|null| 2|
+----+-----+