我有一个csv文件,其中包含以下格式的数据:
id, name, surname, morecolumns
5, John, Lok, more
2, John2, Lok2, more
1, John3, Lok3, more
etc..
我想使用id作为键对我的csv文件进行排序,并将排序后的结果存储在另一个文件中。
到目前为止我为了创建(id,rest_of_line)的JavaPairs而做了什么。
SparkConf conf = new SparkConf().setAppName.....;
JavaSparkContext sc = new JavaSparkContext(conf);
JavaRDD<String> file = sc.textFile("inputfile.csv");
// extract the header
JavaRDD<String> lines = file.filter(s -> !s.equals(header));
// create JavaPairs
JavaPairRDD<Integer, String> pairRdd = lines.mapToPair(
new PairFunction<String, Integer, String>() {
public Tuple2<Integer, String> call(final String line) {
String str = line.split(",", 2)[0];
String str2 = line.split(",", 2)[1];
int id = Integer.parseInt(str);
return new Tuple2(id, str2);
}
});
// sort and save the output
pairRdd.sortByKey(true, 1);
pairRdd.coalesce(1).saveAsTextFile("sorted.csv");
这适用于我有小文件的情况。但是,当我使用更大的文件时,输出未正确排序。我认为这是因为排序过程发生在不同的节点上,所以所有节点的所有过程的合并都不能给出预期的输出。
所以,问题是如何使用id作为键对我的csv文件进行排序,并将排序后的结果存储在另一个文件中。
答案 0 :(得分:0)
方法coalesce
可能是应该责备的方法,因为它显然没有合同保证订购或产生的RDD(见Which operations preserve RDD order?)。因此,如果您避免使用此类coalesce
,则会对所得到的输出文件进行排序。
如果您想要一个唯一的csv
文件,您可以从您正在使用的任何文件系统中获取结果,但要处理它们的实际顺序并合并它们。例如,如果您正在使用HDFS
(如@PinoSan所述),则可以使用命令hdfs dfs -getmerge <hdfs-output-dir> <local-file.csv>
完成此操作。
答案 1 :(得分:0)
正如@mauriciojost指出的那样,你不应该coalesce
。
相反,更好的方法是pairRdd.sortByKey(true,pairRdd.getNumPartitions()).saveAsTextFile(path)
,以便在保存数据的分区上执行最大可能的工作。