未指定行号时使用 MapReduce 进行矩阵转置

Matrix Transpose using MapReduce when there is no Row number specified

考虑到我有大量以下格式的输入

1,2,6,4
4,5,18,7
9,1,3,5
......

输出应该是它的转置
1 4 9 ..
2 5 1 ..
6 6 3 ..
4 7 5 ..

在这种情况下,未指定行号。解析时我们可以获得的列号 假设该文件非常大,将被拆分为多个映射器。由于未指定行号,因此无法确定每个映射器的输出顺序。 因此,是否可以使用另一个 mapreduce 程序预处理输入文件并在将文件发送到 Mapper 之前提供行号?

当您使用 TextInputFormat 时,您会在输入文件中获得作为 LongWritable 键的位置。虽然它实际上不是 row,但您可以在进行输出时使用它对列进行排序。所以整个 map reduce 工作看起来像这样:

public static class TransposeMapper extends Mapper<LongWritable, Text, LongWritable, Text> {
    @Override
    protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
        long column = 0;
        long somethingLikeRow = key.get();
        for (String num : value.toString().split(",")) {
            context.write(new LongWritable(column), new Text(somethingLikeRow + "\t" + num));
            ++column;
        }
    }
}

public static class TransposeReducer extends Reducer<LongWritable, Text, Text, NullWritable> {
    @Override
    protected void reduce(LongWritable key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
        TreeMap<Long, String> row = new TreeMap<Long, String>(); // storing values sorted by positions in input file
        for (Text text : values) {
            String[] parts = text.toString().split("\t"); // somethingLikeRow, value
            row.put(Long.valueOf(parts[0]), parts[1]);
        }
        String rowString = StringUtils.join(row.values(), ' '); // i'm using org.apache.commons library for concatenation
        context.write(new Text(rowString), NullWritable.get());
    }
}