Apache Spark:从行中提取值的问题

use*_*243 1 scala apache-spark apache-spark-sql spark-dataframe apache-spark-dataset

我在 Spark 中的 Row 类遇到了很多问题。在我看来 Row 类是一个真正设计糟糕的类。从 Row 中提取一个值应该并不比从 Scala 列表中提取一个值更困难;但实际上,您必须知道列的确切类型才能提取它。你甚至不能把列变成字符串;对于像 Spark 这样的伟大框架来说,这有多荒谬?在现实世界中,在大多数情况下,您不知道列的确切类型,而且在许多情况下,最重要的是,您有数十个或数百个列。下面是一个示例,向您展示我得到的 ClassCastExceptions。

有没有人有任何解决方案可以轻松地从 Row 中提取值?

scala> val df = List((1,2),(3,4)).toDF("col1","col2")
df: org.apache.spark.sql.DataFrame = [col1: int, col2: int]


scala> df.first.getAs[String]("col1")
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
  ... 56 elided

scala> df.first.getAs[Int]("col1")
res12: Int = 1

scala> df.first.getInt(0)
res13: Int = 1

scala> df.first.getLong(0)
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long
  at scala.runtime.BoxesRunTime.unboxToLong(BoxesRunTime.java:105)
  at org.apache.spark.sql.Row$class.getLong(Row.scala:231)
  at org.apache.spark.sql.catalyst.expressions.GenericRow.getLong(rows.scala:165)
  ... 56 elided

scala> df.first.getFloat(0)
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Float
  at scala.runtime.BoxesRunTime.unboxToFloat(BoxesRunTime.java:109)
  at org.apache.spark.sql.Row$class.getFloat(Row.scala:240)
  at org.apache.spark.sql.catalyst.expressions.GenericRow.getFloat(rows.scala:165)
  ... 56 elided

scala> df.first.getString(0)
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
  at org.apache.spark.sql.Row$class.getString(Row.scala:255)
  at org.apache.spark.sql.catalyst.expressions.GenericRow.getString(rows.scala:165)
  ... 56 elided 
Run Code Online (Sandbox Code Playgroud)

Ram*_*jan 5

Spark 是一个开源项目如果你不喜欢它们,你可以修改它们不要仅仅因为你没有得到你想要的就否定它。有很多选择。Spark 已经变得尽可能灵活。

或者,您可以执行以下操作

df.first.get(0).toString
//res0: String = 1
df.first.get(0).toString.toLong
//res1: Long = 1
df.first.get(0).toString.toFloat
//res2: Float = 1.0
Run Code Online (Sandbox Code Playgroud)

df.first.getAs[Int]("col1").toString
//res0: String = 1
df.first.getAs[Int]("col1").toLong
//res1: Long = 1
df.first.getAs[Int]("col1").toFloat
//res2: Float = 1.0
Run Code Online (Sandbox Code Playgroud)

我再说一遍,如果您对提供的 apis 不满意,您可以随时扩展现有的 apis 并实现您的或创建自己的