如何转换文件与双数组的数据帧在spark



我是Scala和Apache Spark的新手。我的文本文件包含如下条目:

[-0.9704851405656525,1.0286638765434661]
[-0.9704851405656525,1.0286638765434661]
[-1.0353873234576638,-0.001849782262230898]
[-0.9704851405656525,1.0286638765434661]
[-0.9704851405656525,1.0286638765434661]
....

我想从这个创建数据框架。要使用sql查询,我的代码看起来像这样,

def processr(str:String) = str.replaceAll("\[", "").replaceAll("\]","")
case class Result(a:Double, b:Double)
val filemat = sc.textFile("mat.txt")
val result = filemat.map(s => s.split(',').map(r=>Result(processr(r[0]).toDouble, processr(r[1]).toDouble)).toDF.cache

我得到的错误是,

<console>:1: error: identifier expected but integer literal found.
       val result = filemat.map(s => s.split(',').map(r=>Result(processr(r[0]).toDouble, processr(r[1]).toDouble)).toDF.cache

我不确定,我在我的代码做什么错误。看来,我的分割方法是不正确的。谁能建议我的方式转换成数据框架?提前感谢。

应该使用圆括号,而不是方括号。在Scala中,从数组中提取只是一个apply方法调用:

scala> val r = "[-0.9704851405656525,1.0286638765434661]".split(",")
r: Array[String] = Array([-0.9704851405656525, 1.0286638765434661])
scala> r.apply(0)
res4: String = [-0.9704851405656525

和一些语法糖:

scala> r(0)
res5: String = [-0.9704851405656525

接下来你的地图看起来不对。当你调用s.split时,你得到的是Array[String],所以r实际上是String, r(0)给出的是-或第一个数字。您可能需要这样的内容:

filemat.map(_.split(',') match {
  case Array(s1, s2) => Result(processr(s1).toDouble, processr(s2).toDouble)
})

可以通过使用正则表达式的模式匹配来简化:

val p =  "^\[(-?[0-9]+\.[0-9]+),(-?[0-9]+\.[0-9]+)\]$".r
filemat.map{
   case p(s1, s2) => Result(s1.toDouble, s2.toDouble)
}

或使用Row.fromSeq方法:

val schema = StructType(Seq(
  StructField("a", DoubleType, false),
  StructField("b", DoubleType, false)))
val p1 = "(-?[0-9]+\.[0-9]+)".r
sqlContext.createDataFrame(filemat.map(s => 
   Row.fromSeq(p1.findAllMatchIn(s).map(_.matched.toDouble).toSeq)), 
   schema)

相关内容

  • 没有找到相关文章

最新更新