我对Spark中的Row类有很多问题。在我看来,Row类真的是一个设计很差的类。从Row中提取一个值应该不会比从Scala列表中提取一个值更困难;但在实践中,您必须知道列的确切类型才能提取它。您甚至不能将列转换为字符串;对于像Spark这样伟大的框架来说,这是多么荒谬?在现实世界中,在大多数情况下,您不知道列的确切类型,而且在许多情况下,您有数十或数百个列。下面是一个示例,向您展示我一直在获取的ClassCastExceptions。
有没有人有什么解决方案可以轻松地从行中提取值?
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
2条答案
按热度按时间mgdq6dx11#
或者,您可以执行以下操作
和
我再重复一遍,如果您对提供的API不满意,您可以随时扩展现有的API并实现您的API或创建您自己的API
o4tp2gmn2#
它的存在是为了类型安全。如果您不确定列类型,只需将其视为字符串即可,在大多数情况下都适用。(以下是Java示例)