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

时间:2015-05-20 15:47:04

标签: scala apache-spark

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

将一行转换为数组时
SparkDataFrame.map{r => r.toSeq.toArray} 

所有类型信息都丢失了,我找回了[Any]类型的数组。我无法使用

将此对象转换为double
SparkDataFrame.map{r => 
  val array = r.toSeq.toArray 
  array.map(_.toDouble) 
} // Fails with value toDouble is not a member of any

一样
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 

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

SparkDataFrame.map{r => 
  r.getDouble(5)}  

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

我发现的唯一工作如下:

 SparkDataFrame.map{r => 
  doubleArray = Array(r.getInt(5).toDouble, r.getInt(6).toDouble) 
  Vectors.dense(doubleArray) } 

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

任何明确索引行对象的方法?

3 个答案:

答案 0 :(得分:10)

让我们一起看看你的代码块

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

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

SparkDataFrame.map{r => 
  val array = r.toSeq.toArray 
  array.map(_.toDouble) 
} 

_.toDouble不是一个演员..你可以在一个字符串上或在你的情况下一个整数,它将改变变量类型的实例。如果您在Int上调用_.toDouble,则更像是在执行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

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

如果有效

SparkDataFrame.map{r => 
  doubleArray = Array(r.getInt(5).toDouble, r.getInt(6).toDouble) 
  Vectors.dense(doubleArray) } 

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

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

答案 1 :(得分:3)

你应该使用java中的Double.parseDouble。

<div class="col-sm-12 primary" ng-if="isAuthenticated">
        <div class="col-sm-2"><a href="#" class="ui-btn ui-shadow ui-corner-all personal">PERSONALINFO</a></div>
        <div class="col-sm-2"><a href="login.php" class="ui-btn ui-shadow ui-corner-all">LOGOUT</a></div>
   </div> 

答案 2 :(得分:0)

有一个类似的,更难的问题,因为我的功能并非都是Double。以下是我能够从我的DataFrame(从Hive表中拉出)转换为LabeledPoint RDD的方法:

val loaff = oaff.map(r => 
  LabeledPoint(if (r.getString(classIdx)=="NOT_FRAUD") 0 else 1, 
  Vectors.dense(featIdxs.map(r.get(_) match {case null => Double.NaN 
                                             case d: Double => d 
                                             case l: Long => l}).toArray)))