将Spark Row转换为键入的双打数组

use*_*995 13 scala apache-spark

我正在使用带有Hive的Spark 1.3.1,并且有一个行对象,它是一系列传递给Vecors.dense构造函数的双重对象,但是当我通过一个行转换为一个数组时

SparkDataFrame.map{r => r.toSeq.toArray} 
Run Code Online (Sandbox Code Playgroud)

丢失所有类型信息,然后返回[Any]类型的数组.我无法将此对象强制转换为使用

SparkDataFrame.map{r => 
  val array = r.toSeq.toArray 
  array.map(_.toDouble) 
} // Fails with value toDouble is not a member of any
Run Code Online (Sandbox Code Playgroud)

同样如此

SparkDataFrame.map{r => 
      val array = r.toSeq.toArray 
      array.map(_.asInstanceOf[Double]) 
    } // Fails with java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Double 
Run Code Online (Sandbox Code Playgroud)

我看到Row对象有一个API,支持通过以下方式将特定元素作为类型获取:

SparkDataFrame.map{r => 
  r.getDouble(5)}  
Run Code Online (Sandbox Code Playgroud)

但是事件失败,java.lang.Integer无法转换为java.lang.Double

我发现的唯一工作如下:

 SparkDataFrame.map{r => 
  doubleArray = Array(r.getInt(5).toDouble, r.getInt(6).toDouble) 
  Vectors.dense(doubleArray) } 
Run Code Online (Sandbox Code Playgroud)

然而,当索引5到1000需要转换为双精度数组时,这是非常繁琐的.

有没有明确索引行对象?

bwa*_*wok 10

让我们逐个看看你的代码块

SparkDataFrame.map{r => 
  val array = r.toSeq.toArray 
  val doubleArra = array.map(_.toDouble) 
} // Fails with value toDouble is not a member of any
Run Code Online (Sandbox Code Playgroud)

Map返回最后一个语句作为类型(即Scala中的任何函数都有一种隐含的返回值,即最后一个结果是返回值).你的最后一个语句是Unit类型(如Void)..因为将一个变量赋值给val没有返回.要解决这个问题,请取出作业(这样可以减少要阅读的代码).

SparkDataFrame.map{r => 
  val array = r.toSeq.toArray 
  array.map(_.toDouble) 
} 
Run Code Online (Sandbox Code Playgroud)

_.toDouble不是一个演员..你可以在一个字符串上或在你的情况下一个整数,它将改变变量类型的实例.如果你打电话_.toDouble给Int,那更像是在做Double.parseDouble(inputInt).

_.asInstanceOf[Double]将是一个演员...如果你的数据真的是一个双,将改变类型.但不确定你是否需要施放在这里,如果可以,请避免施法.

更新

所以你把代码改成了这个

SparkDataFrame.map{r => 
  val array = r.toSeq.toArray 
  array.map(_.toDouble) 
} // Fails with value toDouble is not a member of any
Run Code Online (Sandbox Code Playgroud)

您在SparkDataFrame的节点上调用了toDouble.显然它不是具有toDouble方法的东西..即它不是Int或String或Long.

如果这样的话

SparkDataFrame.map{r => 
  doubleArray = Array(r.getInt(5).toDouble, r.getInt(6).toDouble) 
  Vectors.dense(doubleArray) } 
Run Code Online (Sandbox Code Playgroud)

但你需要做5到1000 ..为什么不这样做

SparkDataFrame.map{r => 
  val doubleArray = for (i <- 5 to 1000){
      r.getInt(i).toDouble
  }.toArray
  Vectors.dense(doubleArray) 
 } 
Run Code Online (Sandbox Code Playgroud)

  • 后代(for(i < - 2 to record.size)yield record.getInt(i).toDouble).toArray (2认同)