【发布时间】:2016-10-29 14:19:43
【问题描述】:
我想在 AWS 中创建一个数据处理管道,最终将处理后的数据用于机器学习。
我有一个 Scala 脚本,它从 S3 获取原始数据,对其进行处理并使用 Spark-CSV 将其写入 HDFS 甚至 S3。如果我想使用 AWS 机器学习 工具来训练预测模型,我想我可以使用多个文件作为输入。但如果我想使用其他东西,我认为最好接收单个 CSV 输出文件。
目前,由于出于性能目的我不想使用 repartition(1) 或 coalesce(1),因此我使用了 hadoop fs -getmerge 用于手动测试,但由于它只是合并作业输出文件的内容,我遇到了一个小问题。我需要在数据文件中单行标题来训练预测模型。
如果我对 spark-csv 使用 .option("header","true"),那么它将标头写入每个输出文件,合并后,我在数据中拥有与输出文件一样多的标头行。但如果 header 选项为 false,则不会添加任何 headers。
现在我找到了一个选项,可以将 Scala 脚本中的文件与 Hadoop API FileUtil.copyMerge 合并。我用下面的代码在spark-shell 中尝试了这个。
import org.apache.hadoop.fs.FileUtil
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
val configuration = new Configuration();
val fs = FileSystem.get(configuration);
FileUtil.copyMerge(fs, new Path("smallheaders"), fs, new Path("/home/hadoop/smallheaders2"), false, configuration, "")
但是这个解决方案仍然只是将文件连接在一起并且不处理标题。 如何获得只有一行标题的输出文件?
我什至尝试添加 df.columns.mkString(",") 作为 copyMerge 的最后一个参数,但这仍然多次添加标题,而不是一次。
【问题讨论】:
-
我也面临同样的问题。这个问题解决了吗?
-
如何将 DataFrame 过滤为零行,使用 header=true 导出,使用 header=false 导出其余数据,然后将 header 与分区合并?
-
@Boern 这可能有效。虽然我认为这需要将头文件复制到与数据相同的输出并确保它始终是第一个文件。我认为这个当前的解决方案不允许写入相同的路径。当然附加可能会解决这个问题,需要尝试一段时间。
-
@bleka “如何”是这个问题的重点。可以想象一个触发标志,告诉它只保存带有指定文件
part-0000的标题,或者可能是一种智能串联,它将多个工作人员保存的文件组合在一起,但只保留其中一个工作人员的标题。copyMerge看起来它只是组合文件,所以如果文件有标题,标题将出现多次,或者如果文件没有标题,则根本没有标题,正如 V. Samma 在问题中所说。还是copyMerge在您的回答中有不同的行为? -
@belka 虽然这些不是具有不同列的不同数据帧,但它们只是具有相同列的同一数据帧的不同分区
标签: scala csv hadoop apache-spark