未指定行号时使用 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());
}
}
考虑到我有大量以下格式的输入
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());
}
}