仅选择至少包含一个非 null 值的列的惯用方法



什么是最惯用(也是最有效的)方法,只选择那些包含至少一个 NOT NULL 值的数据帧/数据集列。

即具有以下数据集:

+----+----+------+----+---------------------+----+
|int1|int2|str1  |str2|dt1                  |dt2 |
+----+----+------+----+---------------------+----+
|1   |null|strin1|null|null                 |null|
|null|null|null  |null|2000-01-03 12:12:12.0|null|
+----+----+------+----+---------------------+----+

我将如何获得以下一个:

+----+------+---------------------+
|int1|str1  |dt1                  |
+----+------+---------------------+
|1   |strin1|null                 |
|null|null  |2000-01-03 12:12:12.0|
+----+------+---------------------+

有一个适用于Apache Spark版本1.6.0 +的解决方案会很好

数据设置:

case class C(int1: Integer, int2: Integer, str1: String, str2: String, dt1: String, dt2: String)
val cc = Seq(
C(1, null, "strin1", null, null, null),
C(null, null, null, null, "2000-01-03 12:12:12", null)
)
val t = sc.parallelize(cc, 2).toDF()
val df = t.withColumn("dt1", $"dt1".cast("timestamp")).withColumn("dt2", $"dt2".cast("timestamp"))

更新:

PS感谢@user8371915指出非常相似的问题。我想让这个问题悬而未决,希望找到一个更优雅的解决方案 - 我试图找到一种方法来使用类似的东西:

df.columns.filter(c => when(count(col(c))>0,c))

但是我不知道如何正确地做到这一点...

使用与这个伟大答案中描述的方法非常相似的方法:

val cols = df.select(df.columns.map(c => count(col(c)).alias(c)): _*)
.collect()(0)
.toSeq.zipWithIndex
.filter(_._1 != 0).map(_._2)
.map(i => df.columns.apply(i))

这为我们提供了一个我们正在寻找的列数组:

scala> cols
res125: Seq[String] = ArrayBuffer(int1, str1, dt1)

现在我们可以选择这些列:

scala> df.select(cols.head, cols.tail: _*).show
+----+------+--------------------+
|int1|  str1|                 dt1|
+----+------+--------------------+
|   1|strin1|                null|
|null|  null|2000-01-03 12:12:...|
+----+------+--------------------+

scala> df.select(cols.map(col): _*).show
+----+------+--------------------+
|int1|  str1|                 dt1|
+----+------+--------------------+
|   1|strin1|                null|
|null|  null|2000-01-03 12:12:...|
+----+------+--------------------+

相关内容

  • 没有找到相关文章

最新更新