从Dataframe中删除所有具有一个值的列(效率更高)

时间:2018-05-16 10:29:33

标签: scala apache-spark apache-spark-sql

假设我有以下数据框:

   /*
+---------+--------+----------+--------+
|a        |b       |      c   |d       |
+---------+--------+----------+--------+
|      bob|      -1|         5|      -1|
|    alice|      -1|        -1|      -1|
+---------+--------+----------+--------+
*/

我想删除所有行中只有-1的列(在本例中为bd)。我找到了一个解决方案,但是当我开始工作时,我发现它的效率很低:

private def removeEmptyColumns(df: DataFrame): DataFrame = {
    val types = List("IntegerType", "DoubleType", "LongType")
    val dTypes: Array[(String, String)] = df.dtypes
    dTypes.foldLeft(df)((d, t) => {
      val colType = t._2
      val colName = t._1
      if (types.contains(colType)) {
        if (colType.equals("IntegerType")) {
          if (d.select(colName).filter(col(colName) =!= -1).take(1).length == 0) d.drop(colName)
          else d
        } else if (colType.equals("DoubleType")) {
          if (d.select(colName).filter(col(colName) =!= -1.0).take(1).length == 0) d.drop(colName)
          else d
        } else {
          if (d.select(colName).filter(col(colName) =!= -1).take(1).length == 0) d.drop(colName)
          else d
        }
      } else {
        d
      }
    })
  }

是否有更好的解决方案或方法来改进我现有的代码?

(我认为这一行val count = d.select(colName).distinct.count是瓶颈)

我正在使用Spark 2.2 atm。

非常感谢

1 个答案:

答案 0 :(得分:0)

不要计算不同值的数量,而是尝试检查是否存在任何其他不是-1的值

d.select(colName).filter(_ != -1).take(1).length == 0

另一种方法

您可以尝试一次性收集统计信息,而不是遍历数据框n次(每列一次)

val summary = d.agg(
      max(col1).as(s"${col1}_max"), min(col1).as(s"${col1}_min")), 
      max(col2).as(s"${col1}_max"), min(col2).as(s"${col2}_min")), 
       ...)
      .first    

然后比较该列的minmax值是否相同-1