java - que - mapreduce la diferencia en el conteo
mongodb español (1)
Intento escribir un programa que muestre las diferencias entre recuentos en 2 columnas. Entonces mis datos se ven así:
2,1
2,3
1,2
3,1
4,2
Quiero contar las ocurrencias de clave en col1 y las ocurrencias de claves en col2 y tomar la diferencia. La salida debería verse así:
1,-1
2,0
3,0
4,1
¿se puede hacer esto en un procedimiento mapreduce (mapper, reducer)?
En el mapeador de cada línea, creará dos claves, una para col1 y otra para col2, donde los valores se cuentan de cada columna, así:
2,1 -> 2: {1, 0} y 1: {0, 1}
2,3 -> 2: {1, 0} y 3: {0, 1}
1,2 -> 1: {1, 0} y 2: {0, 1}
3,1 -> 3: {1, 0} y 1: {0, 1}
4,2 -> 4: {1, 0} y 2: {0, 1}
Luego en el reductor obtendrá estos resultados donde cada línea es la combinación de clave y valores para cada llamada de reduce
:
1 -> {0, 1}, {1, 0}, {0, 1} (agregarlos producirá -1)
2 -> {1, 0}, 2: {1, 0}, 2: {0, 1}, 2: {0, 1} (agregarlos producirá 0)
3 -> {0, 1}, {1, 0} (agregarlos producirá 0)
4 -> {1, 0} (agregarlos producirá 1)
Actualizar:
Aquí está el ejemplo de Hadoop (no está probado y puede requerir algunos ajustes para que funcione):
public class TheMapper extends Mapper<LongWritable, Text, Text, ArrayPrimitiveWritable>{
protected void map(LongWritable offset, Text value, Context context)
throws IOException, InterruptedException {
StringTokenizer tok = new StringTokenizer( value.toString(), "," );
Text col1 = new Text( tok.nextToken() );
context.write( col1, toArray(1, 0) );
Text col2 = new Text( tok.nextToken() );
context.write( col2, toArray(0, 1) );
}
private ArrayPrimitiveWritable toArray(int v1, int v2){
return new ArrayPrimitiveWritable( new int[]{i1, i2} );
}
}
public class TheReducer extends Reducer<Text, ArrayPrimitiveWritable, Text, Text> {
public void reduce(Text key, Iterable<ArrayPrimitiveWritable> values, Context context)
throws IOException, InterruptedException {
Iterator<ArrayPrimitiveWritable> i = values.iterator();
int count = 0;
while ( i.hasNext() ){
int[] counts = (int[])i.next().get();
count += counts[0];
count -= counts[1];
}
context.write( key, new Text("" + count) );
}
}