【问题标题】:spark select columns by typespark 按类型选择列
【发布时间】:2019-07-13 20:20:11
【问题描述】:

我想要一个函数来按数据类型动态选择 spark Dataframe 列。

到目前为止,我已经创建了:

object StructTypeHelpers {
  def selectColumnsByType[T <: DataType](schem: StructType):Seq[String] = {
    schem.filter(_.dataType.isInstanceOf[T]).map(_.name)
  }

}

这样StructTypeHelpers. selectColumnsByType[StringType](df.schema) 应该可以工作。但是,编译器警告我:

abstract type T is unchecked since it is eliminated by erasure

尝试使用时:

import scala.reflect.ClassTag
def selectColumnsByType[T <: DataType: ClassTag](schem: StructType):Seq[String]

失败了

No ClassTag available for T

如何在没有警告的情况下让它工作和编译?

【问题讨论】:

  • 答案很明显,只需添加 TypeTag 或 ClassTag 等 docs.scala-lang.org/overviews/reflection/…,因为您没有在方法中提供有关类型 T 的信息。
  • 但这不应该是:T &lt;: DataType: ClassTag 吗?这失败了:No ClassTag available for T
  • 您必须隐式提供 TypeTag / ClassTag 信息,这有点痛苦,但效果很好
  • 你的意思是:stackoverflow.com/questions/18136313/…?但它似乎还没有真正起作用。
  • 不,这不是我的意思,像 def paramInfo[T](x: T)(implicit tag: TypeTag[T]),根据我的第一个链接,它真的应该工作,抱歉,应该把这个作为答案:)

标签: scala apache-spark generics


【解决方案1】:

我们的想法是仅过滤具有您想要的类型的列,然后进行选择。

val df  =  Seq(
  (1, 2, "hello")
).toDF("id", "count", "name")

import org.apache.spark.sql.functions.col
def selectByType(colType: DataType, df: DataFrame) = {

  val cols = df.schema.toList
    .filter(x => x.dataType == colType)
    .map(c => col(c.name))
  df.select(cols:_*)

}
val res = selectByType(IntegerType, df)

【讨论】:

  • 但是这个方案只支持equals,不支持:isInstanceOf[columnDataType]
  • 为什么要使用 asInstanceOf ?
  • 关于类型层次结构不是更安全吗?但是你可能是正确的,对于原始类型 spark 支持它没有任何区别。
  • 有谁知道如何在 pyspark 中做到这一点?
猜你喜欢
  • 1970-01-01
  • 2023-03-29
  • 2021-04-03
  • 2012-08-14
  • 2016-06-13
  • 1970-01-01
  • 1970-01-01
  • 2010-11-07
  • 1970-01-01
相关资源
最近更新 更多