使用Scala和Spark创建RDD并输出到文本文件

使用Scala和Spark创建RDD并输出到文本文件,scala,apache-spark,Scala,Apache Spark,我很抱歉这可能是一个简单的问题,但我正在努力用scala/spark解析rdd。我有一个从CSV创建的RDD,用 val partitions: RDD[(String, String, String, String, String)] = withoutHeader.mapPartitions(lines => { val parser = new CSVParser(',') lines.map(line => {

我很抱歉这可能是一个简单的问题,但我正在努力用scala/spark解析rdd。我有一个从CSV创建的RDD,用

    val partitions: RDD[(String, String, String, String, String)] = withoutHeader.mapPartitions(lines => {
            val parser = new CSVParser(',')
            lines.map(line => {
                    val columns = parser.parseLine(line)
                    (columns(0), columns(1), columns(2), columns(3), columns(4))
            })
    })
当我将其输出到具有

partitions.saveAsTextFile(file)
我得到了每一行都有括号的输出。我不要这些括号。总的来说,我很难理解这里发生了什么。我的背景是低级语言,我正努力从抽象中了解它实际上在做什么。我理解映射,但我不理解的是输出。有人能给我解释一下行
(第(0)列、第(1)列、第(2)列、第(3)列、第(4)列)中发生了什么事吗?
,或者给我指一个简单解释发生了什么事的指南

我的最终目标是能够在spark中操作hdsf上的文件,将它们转换为适合mllib的格式。我对spark或scala指南不感兴趣,因为它们看起来像是用注释不好的Javadoc生成的,并且没有真正解释任何内容

提前谢谢


Dean

我只想把你的元组转换成你想要的字符串格式。例如,要创建|分隔的输出:

partitions.map{tup=>s“${tup.\u 1}}${tup.\u 2}${tup.\u 3}}${tup.\u 4}${tup.\u 5}”

或者使用模式匹配(这会带来更多的运行时开销):

partitions.map{case(a,b,c,d,e)=>s“$a |$b |$c |$d |$e”}

我正在使用Scala的字符串插值功能(注意
s“…”
格式)

请注意,您可以通过将RDD作为一个整体而不是单个分区进行映射来简化示例:

val parser = new CSVParser(',')
val partitions: RDD[(String, String, String, String, String)] = 
  withoutHeader.map { line => 
    val columns = parser.parseLine(line)
    (columns(0), columns(1), columns(2), columns(3), columns(4))
  }

我会把你的元组转换成你想要的字符串格式。例如,要创建|分隔的输出:

partitions.map{tup=>s“${tup.\u 1}}${tup.\u 2}${tup.\u 3}}${tup.\u 4}${tup.\u 5}”

或者使用模式匹配(这会带来更多的运行时开销):

partitions.map{case(a,b,c,d,e)=>s“$a |$b |$c |$d |$e”}

我正在使用Scala的字符串插值功能(注意
s“…”
格式)

请注意,您可以通过将RDD作为一个整体而不是单个分区进行映射来简化示例:

val parser = new CSVParser(',')
val partitions: RDD[(String, String, String, String, String)] = 
  withoutHeader.map { line => 
    val columns = parser.parseLine(line)
    (columns(0), columns(1), columns(2), columns(3), columns(4))
  }

我会把你的元组转换成你想要的字符串格式。例如,要创建|分隔的输出:

partitions.map{tup=>s“${tup.\u 1}}${tup.\u 2}${tup.\u 3}}${tup.\u 4}${tup.\u 5}”

或者使用模式匹配(这会带来更多的运行时开销):

partitions.map{case(a,b,c,d,e)=>s“$a |$b |$c |$d |$e”}

我正在使用Scala的字符串插值功能(注意
s“…”
格式)

请注意,您可以通过将RDD作为一个整体而不是单个分区进行映射来简化示例:

val parser = new CSVParser(',')
val partitions: RDD[(String, String, String, String, String)] = 
  withoutHeader.map { line => 
    val columns = parser.parseLine(line)
    (columns(0), columns(1), columns(2), columns(3), columns(4))
  }

我会把你的元组转换成你想要的字符串格式。例如,要创建|分隔的输出:

partitions.map{tup=>s“${tup.\u 1}}${tup.\u 2}${tup.\u 3}}${tup.\u 4}${tup.\u 5}”

或者使用模式匹配(这会带来更多的运行时开销):

partitions.map{case(a,b,c,d,e)=>s“$a |$b |$c |$d |$e”}

我正在使用Scala的字符串插值功能(注意
s“…”
格式)

请注意,您可以通过将RDD作为一个整体而不是单个分区进行映射来简化示例:

val parser = new CSVParser(',')
val partitions: RDD[(String, String, String, String, String)] = 
  withoutHeader.map { line => 
    val columns = parser.parseLine(line)
    (columns(0), columns(1), columns(2), columns(3), columns(4))
  }


你能展示一下你的输出文件的样本吗?输出文件如下:(3.5,1.4,0.2,setosa)(3,1.4,0.2,setosa)(3.2,1.3,0.2,setosa)(3.1,1.5,0.2,setosa)(3.6,1.4,0.2,setosa)你能展示一下你的输出文件的样本吗?输出文件如下:(3.5,1.4,0.2,setosa)(3,1.3,0.2,setosa)(3.1,setosa)(3.1,0.1,setosa)(3.6,1.4,0.2,setosa)你能展示一下你的输出文件吗?输出文件如下:(3.5,1.4,0.2,setosa)(3,1.4,0.2,setosa)(3.2,1.3,0.2,setosa)(3.1,1.5,0.2,setosa)(3.6,1.4,0.2,setosa)你能展示一下你的输出文件吗(3.1,1.5,0.2,刚毛)(3.6,1.4,0.2,刚毛)如果我将RDD作为一个整体进行映射,那么如果我通过一个Thread作业在分布式系统上处理一个巨大的文件,这会影响性能吗?使用Thread处理单个分区感觉应该更有效,尽管这只是基于我认为并行化可能的工作方式。+1我没有考虑就太复杂了先简单点:)。至于上述问题。这取决于CSVParser的实际成本。使用mapPartitions的最大原因是减少实例化。如果它是一个简单的解析器,那么创建一次并通过网络发送就可以了。您所做的只是在看似不必要的地方进行微管理。同意。
RDD.map
Actualy使用了一个
mapPartition
变体,因此除非您需要更细粒度的控件,否则显式调用它没有多大好处。完美。感谢您的两个输入。Justin,您的解决方案可能更复杂,但我感谢您对后台发生的事情的解释。非常有用。如果我在RDD作为一个整体,如果我通过Thread作业在分布式系统上处理一个巨大的文件,这对性能有影响吗?使用Thread处理单个分区感觉应该更有效,尽管这只是基于我认为并行化可能的工作方式。+1我太复杂了,没有先考虑简单:)。关于上述问题。这取决于CSVParser到底有多贵。使用mapPartitions的最大原因是减少实例化。如果它是一个简单的解析器,那么创建一次并通过网络发送就可以了。你所做的只是在看似不必要的地方进行微观管理。同意<代码>关系图