从DataFrame到Array的不同值

时间:2016-05-18 08:32:30

标签: scala apache-spark

我试图将DataFrame(名为:df)的单个列的不同值放入与列的数据类型匹配的数组中。这是我尝试过的,但它不起作用:

def distinctValues[T: ClassTag](column: String): Array[T] = {
      df.select(df(column)).distinct.map {
        case Row(s: T) => s
      }.collect
    }

该方法位于隐式类中,因此调用df.distinctValues("some_col")会给我:

scala.MatchError: [ABCD] (of class org.apache.spark.sql.catalyst.expressions.GenericRowWithSchema)

是否有一种优雅的方式来实现我想要的类型安全?

我在Spark 1.4.1上。

2 个答案:

答案 0 :(得分:3)

问题在于您使用模式匹配而不是getAs方法:

implicit final class DataFrameOps(val df: DataFrame) {
  def distinctValues[T: ClassTag](column: String): Array[T] = {
     df.select(column).distinct().map(_.getAs[T](column)).collect()
  }
}

用法:

val ageArray: Array[Int] = df.distinctValues("age")
or
val ageArray = df.distinctValues[Int]("age")

答案 1 :(得分:1)

从1.4.0开始,Spark有dropDuplicates方法通过列序列(或所有列,如果没有指定)实现不同的方法:

//drop duplicates considering specified columns
val distinctDf = df.select($"column").dropDuplicates(Seq("column"))
//this should work too since df has one column after select
val distinctDf = df.select($"column").dropDuplicates()
//collect
def getValues[T](df: DataFrame, columnName: String) = {
  df.map(_.getAs[T](columnName)).collect()
}

getValues[String](distinctDf, "column")