仅选择那些包含至少一个NOT NULL值的DataFrame / DataSet列的最惯用(和有效)方法是什么。
即。拥有以下数据集:
+----+----+------+----+---------------------+----+
|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指向very similar question。我想打开这个问题,希望找到一个更优雅的解决方案 - 我试图找到一种方法来使用类似的东西:
df.columns.filter(c => when(count(col(c))>0,c))
但我无法弄清楚如何正确地做到这一点......
答案 0 :(得分:1)
使用an approach very similar to one described in this great answer:
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:...|
+----+------+--------------------+