Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/apache-spark/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何有效地从单个字符串RDD中提取多个列?_Scala_Apache Spark - Fatal编程技术网

Scala 如何有效地从单个字符串RDD中提取多个列?

Scala 如何有效地从单个字符串RDD中提取多个列?,scala,apache-spark,Scala,Apache Spark,我有一个包含20多列的文件,我想从中提取一些。到目前为止,我有以下代码。我相信有一个聪明的方法可以做到这一点,但无法让它成功运行。有什么想法吗 mvnmdata的类型为RDD[String] val strpcols=mvnmdata.map(x=>x.split(“|”).map(x=>(x(0)、x(1)、x(5)、x(6)、x(7)、x(8)、x(9)、x(10)、x(11)、x(12)、x(13)、x(14)、x(15)、x(16)、x(17)、x(18)、x(19)、x(20)、x(2

我有一个包含20多列的文件,我想从中提取一些。到目前为止,我有以下代码。我相信有一个聪明的方法可以做到这一点,但无法让它成功运行。有什么想法吗

mvnmdata的类型为RDD[String]

val strpcols=mvnmdata.map(x=>x.split(“|”).map(x=>(x(0)、x(1)、x(5)、x(6)、x(7)、x(8)、x(9)、x(10)、x(11)、x(12)、x(13)、x(14)、x(15)、x(16)、x(17)、x(18)、x(19)、x(20)、x(21)、x(22)、x(23)))```

如下所示,如果您不想写入重复的x(i),可以在循环中处理它。例1:

val strpcols = mvnmdata.map(x => x.split('|'))
  .map(x =>{
    val xbuffer = new ArrayBuffer[String]()
    for (i <- Array(0,1,5,6...)){
      xbuffer.append(x(i))
    }
    xbuffer
  })
您想要的最终代码:

  //define the function to process indexes
  def getSpecIndexes(start:Int, end:Int, removedValueSet:Set[Int]):Array[Int] = {
    ((start to end).toSet -- removedValueSet).toArray.sortBy(row=>row)
  }

  val strpcols = mvnmdata.map(x => x.split('|'))
    .map(x =>{
      val xbuffer = new ArrayBuffer[String]()
      //call the function
      for (i <- getSpecIndexes(0,100,Set(3,4,5,6))){
        xbuffer.append(x(i))
      }
      xbuffer
    })
//定义处理索引的函数
def getSpecIndexes(开始:Int,结束:Int,removedValueSet:Set[Int]):数组[Int]={
((从开始到结束).toSet--removedValueSet.toArray.sortBy(行=>row)
}
val strpcols=mvnmdata.map(x=>x.split(“|”))
.map(x=>{
val xbuffer=新阵列缓冲[字符串]()
//调用函数

对于(i,下一个解决方案提供了一种简单且可扩展的方法来管理列名和索引。它基于一个确定列名/索引关系的映射。该映射还将帮助我们处理提取列的索引及其名称

import org.apache.spark.sql.Row
import org.apache.spark.sql.types.{StringType, StructType, StructField}

val rdd = spark.sparkContext.parallelize(Seq(
"1|500|400|300",
"1|34|67|89",
"2|10|20|56",
"3|2|5|56",
"3|1|8|22"))

val dictColums = Map("c0" -> 0, "c2" -> 2)

// create schema from map keys
val schema = StructType(dictColums.keys.toSeq.map(StructField(_, StringType, true)))

val mappedRDD = rdd.map{line => line.split('|')}
                    .map{
                      cols => Row.fromSeq(dictColums.values.toSeq.map{cols(_)})
                    }

val df = spark.createDataFrame(mappedRDD, schema).show

//output
+---+---+
| c0| c2|
+---+---+
|  1|400|
|  1| 67|
|  2| 20|
|  3|  5|
|  3|  8|
+---+---+
  • 首先,我们声明dictColums,在本例中,我们将提取cols“c0”->0和“c2”->2
  • 接下来,我们从映射的键创建模式
  • 一个映射(您已经拥有)将按
    |
    分割行,第二个映射将创建一个
    ,其中包含与
    dictColums.values的每个项目相对应的值
更新:

您还可以从上述功能创建一个功能,以便能够多次重用它:

import org.apache.spark.sql.DataFrame
def stringRddToDataFrame(colsMapping:Map[String,Int],rdd:rdd[String]):数据帧={
val schema=StructType(colsMapping.keys.toSeq.map(StructField(_,StringType,true)))
val mappedRDD=rdd.map{line=>line.split('|')}
.地图{
cols=>Row.fromSeq(colsMapping.values.toSeq.map{cols()})
}
createDataFrame(mappedRDD,模式)
}
然后将其用于您的案例:

val cols=Map(“c0”->0,“c1”->1,“c5”->5,…“c23”->23)
val df=stringRddToDataFrame(cols,rdd)

执行上述代码时出现了什么样的错误?是不是“元组中的元素太多”之类的问题?没有错误,我得到了预期的结果。但我在想,如果没有“x(n)”的话,是否有一条捷径可以编写相同的命令重复。谢谢。这就是我要找的!抱歉,没有看到。现在无法更改。上面的解决方案在我的版本(Scala 2.11)中不起作用,您是在哪个版本编写的?您能描述一下您遇到的错误吗?我的Scala版本也是2.11。您可以定义一个函数,然后在Eample 1的映射块中调用该函数。现在我已经编写了上面的最终代码。函数getSpecIndexes正是您想要的。请查看它。感谢您的解决方案。我需要一点时间来完成了解每个步骤背后发生的事情!感谢您的时间。当然,请慢慢来。在这中间有一些进一步的细节:1.我们基于dictColums映射的键创建架构。首先,我们创建一个StructType,通过将每个键映射到一个新的StructField实例,其中键是名称,而e类型将是StringType(如果愿意,您可以更改它以支持更多类型)。在我们的示例中,c0、c1将是架构的列名。2.我们在
|
上拆分每一行,这将生成一个strings3数组。对于每个数组,我们生成一个新的行实例,其中包含使用
dictColums.values.toSeq.map提取的元素{cols()}
。最后一个使用字典的值从数组中提取所需的列,字典的值实际上是所需的数组索引。对于c0,索引为0,对于c2,索引为2。对应于这两个
x(0),x(2)的值
也将是新创建行的内容。4.最后,我们使用mappedRDD和schema填充一个新的数据框
import org.apache.spark.sql.Row
import org.apache.spark.sql.types.{StringType, StructType, StructField}

val rdd = spark.sparkContext.parallelize(Seq(
"1|500|400|300",
"1|34|67|89",
"2|10|20|56",
"3|2|5|56",
"3|1|8|22"))

val dictColums = Map("c0" -> 0, "c2" -> 2)

// create schema from map keys
val schema = StructType(dictColums.keys.toSeq.map(StructField(_, StringType, true)))

val mappedRDD = rdd.map{line => line.split('|')}
                    .map{
                      cols => Row.fromSeq(dictColums.values.toSeq.map{cols(_)})
                    }

val df = spark.createDataFrame(mappedRDD, schema).show

//output
+---+---+
| c0| c2|
+---+---+
|  1|400|
|  1| 67|
|  2| 20|
|  3|  5|
|  3|  8|
+---+---+