我有一些处理csv文件的spark代码。它对它做了一些改造。我现在想将此RDD保存为csv文件并添加标头。此RDD的每一行都已正确格式化。
我不知道该怎么做。我想用标题字符串和我的RDD进行联合,但标题字符串不是RDD所以它不起作用。
答案 0 :(得分:10)
您可以从标题行中创建一个RDD,然后union
它,是的:
val rdd: RDD[String] = ...
val header: RDD[String] = sc.parallelize(Array("my,header,row"))
header.union(rdd).saveAsTextFile(...)
然后你最终得到了一堆你合并的part-xxxxx
个文件。
问题在于,我不认为您确保标题将成为第一个分区,因此最终会出现在part-00000
和文件顶部。在实践中,我非常肯定它会。
更可靠的是使用像hdfs
这样的Hadoop命令来合并part-xxxxx
文件,并且作为命令的一部分,只需从文件中输入标题行。
答案 1 :(得分:0)
在没有Union的情况下编写它的一些帮助(在合并时提供标题)
val fileHeader ="This is header"
val fileHeaderStream: InputStream = new ByteArrayInputStream(fileHeader.getBytes(StandardCharsets.UTF_8));
val output = IOUtils.copyBytes(fileHeaderStream,out,conf,false)
现在循环遍历文件部分,使用
编写完整的文件val in: DataInputStream = ...<data input stream from file >
IOUtils.copyBytes(in, output, conf, false)
这确保了即使你使用coalasec / repartition进行高效写作,标题总是作为第一行出现
答案 2 :(得分:0)
def addHeaderToRdd(sparkCtx: SparkContext, lines: RDD[String], header: String): RDD[String] = {
val headerRDD = sparkCtx.parallelize(List((-1L, header))) // We index the header with -1, so that the sort will put it on top.
val pairRDD = lines.zipWithIndex()
val pairRDD2 = pairRDD.map(t => (t._2, t._1))
val allRDD = pairRDD2.union(headerRDD)
val allSortedRDD = allRDD.sortByKey()
return allSortedRDD.values
}
答案 3 :(得分:0)
来自问题:我现在想将此RDD保存为CSV文件并添加标题。此RDD的每一行都已正确格式化。
使用Spark 2.x,您可以选择convert RDD to DataFrame
val rdd = .... //Assume rdd properly formatted with case class or tuple
val df = spark.createDataFrame(rdd).toDF("col1", "col2", ... "coln")
df.write
.format("csv")
.option("header", "true") //adds header to file
.save("hdfs://location/to/save/csv")
现在我们甚至可以使用Spark SQL DataFrame来加载,转换和保存CSV文件
答案 4 :(得分:0)
spark.sparkContext.parallelize(Seq(SqlHelper.getARow(temRet.columns,
temRet.columns.length))).union(temRet.rdd).map(x =>
x.mkString("\x01")).coalesce(1, true).saveAsTextFile(retPath)
object SqlHelper {
//create one row
def getARow(x: Array[String], size: Int): Row = {
var columnArray = new Array[String](size)
for (i <- 0 to (size - 1)) {
columnArray(i) = x(i).toString()
}
Row.fromSeq(columnArray)
}
}