MapReduce
un ejemplo sencillo

Existe numerosa bibliografía sobre Map-Reduce por lo que no vale la pena comenzar explicando la técnica pero si es interesante
contar con código de ejemplo para fijar ideas. Esto es lo que vamos a intentar hacer. El lenguaje que vamos a utilizar es Python
y la implementación de Map-Reduce se llama Mincemeat. Se puede descargar libremente en el siguiente repositorio:

Github--> michaelfairley / mincemeatpy

Las instrucciones son sencillas y es una buena implementación de Map-Reduce que nos permite hacer pruebas rápidas y ajustar algoritmos.
Por otro lado necesitamos un dataset y algo para hacer con el dataset. El dataset lo descargamos de

Alumnos por Modalidad y Nivel

La idea es trazar un mapa de la cantidad de alumnos por provincia y por nivel para después confeccionar una infografía.
Con este dataset cualquier programador principiante o cualquiera que maneje mínimamente el Excel puede, en pocos minutos,
hacer una tabla de datos. Pero aquí decidimos utilizar Map-Reduce simplemente porque es mas deportivo.
Nuestro dataset tiene la siguiente estructura:


anio_relevamiento,provincia,cod_provincia,departamento,cod_departamento,sector,modalidad_basica,nivel,alumnos
RA_2011,Ciudad de Buenos Aires,2,I,2001,Estatal,Adultos,Primaria,357
RA_2011,Chaco,22,SARGENTO CABRAL,22154,Estatal,Común,Secundaria,2131
RA_2011,Chaco,22,SARGENTO CABRAL,22154,Estatal,Común,Inicial,719
RA_2011,Ciudad de Buenos Aires,2,I,2001,Estatal,Adultos,Formación Profesional,4357
RA_2011,Chaco,22,SARGENTO CABRAL,22154,Estatal,Común,Secundaria,2131
RA_2011,Chaco,22,SARGENTO CABRAL,22154,Estatal,Común,Inicial,719


Como vemos tiene 9 columnas, solo nos van a interesar la 1 y la la 8 y mas delante la 7 porque los vamos a discriminar
por nivel. Por ahora la columna 1 es la provincia y la 8 es la cantidad de alumnos, recuerden que la primer columna es la 0.
El archivo está desagregado por departamento, sector, modalidad y nivel. Nosotros vamos a obtener un consolidado por provincia.
Lo primero que tenemos que hacer es cargar el csv, no nos olvidemos que debemos obtener los datos de la forma

{clave:valor}

para de esa forma poder entregarsela al mapper. La lectura la hacemos con el siguiente código en Python:


  import sys
  import csv
  fname = sys.argv[1]
  col_n = int(sys.argv[2])
  col_v = int(sys.argv[3])
  f = open(fname, 'r') # Abrir el CSV file
  allrows = csv.reader(f, dialect=csv.excel)
  primeraEtapa = {}
  errores =0
  index=0
  for index, row in enumerate(allrows):
          b = string.join (row, ',')
          primeraEtapa[index]=[row[col_n]+","+row[col_v]]s = mincemeat.Server()


  s.datasource = primeraEtapa
  s.mapfn = mapfn
  s.reducefn = reducefn
  resultado = s.run_server(password="changeme")
  print "resultados",resultado



Como vemos estamos armando un diccionario que tiene un índice como clave y algo de la forma "provincia,cantidad"
como valor esto es lo que va a recibir el mapper. La última parte es para llamar al mincemeat. Entonces pasemos al mapper.


  def mapfn(key,val):
          for w in val:
                    provincia = w.split(",")[0]
                    cantidad = w.split(",")[1]
                    yield provincia, int(cantidad)



El mapper lo único que hace es tomar los valores del diccionario que habíamos armado, los separa en dos para eso
le pusimos la coma (recordar que lo que recibió el mapper es de la forma {indice:provincia,cantidad}) descarta el
índice y toma como clave para el reducer la provincia y como valor la cantidad de alumnos. Ahora vamos a ver la función reduce:


  def reducefn(provincia, cantidad):
  result = 0
  for v in provincia:
        result = sum(cantidad)
        print provincia, sum(cantidad)
        return provincia, result


Nuevamente es muy sencilla, lo único que hace es sumar la cantidad de alumnos. Recordemos que el reducer lo que hace
es clasificar por clave y, en este caso sumar las cantidades y devuelve todo al servidor.
El código completo se puede descargar del repositorio Github--> gvillamayor / MREducacion1
Están todos los archivos incluidos los datos. Para ejecutarlo hay que tener el Python 2.7 instalado con las slibrerías correspondientes
fundamentalmente la librería csv, y ejecutar primero el archivo "secundario.bat" esto va a correr el servidor. Una vez
que tengamos funcionando el servidor ejecutamos el archivo "cliente.bat". La salida a trvez de la instrucción print de la funcion reducefn se
redirecciona a un archivo que se llama "salida.txt" además de devolver los datos al servidor. La salida que obtuvimos es la siguiente:


        San Juan 212321
        Córdoba 929726
        Chaco 400451
        Mendoza 521526
        Chubut 159807
        San Luis 126661
        Tucumán 454534
        Misiones 388375
        Corrientes 361515
        Formosa 209713
        Río Negro 196731
        Buenos Aires 4373418
        Santa Cruz 92169
        Tierra del Fuego 47175
        Neuquén 187203
        Santiago del Estero 287842
        La Pampa 88584
        Ciudad de Buenos Aires 805251
        Jujuy 251048
        Catamarca 131805
        Salta 426570
        La Rioja 113383
        Entre Ríos 379293
        Santa Fe 829210


Se pueden ejecutar tantas copias de "cliente.bat" como se quiera solo hay que cambiar el nombre del archivo de salida
incluso en distintos equipos para esto hay que colocarle la dirección IP del equipo donde está el servidor en la linea de comando
Por ejemplo ejecutando dos copias se obtienen los siguientes archivos de salida:


        San Juan 212321
        Chaco 400451
        Chubut 159807
        Tucumán 454534
        Corrientes 361515
        Río Negro 196731
        Santa Cruz 92169
        Tierra del Fuego 47175
        Neuquén 187203
        La Pampa 88584
        Jujuy 251048
        Salta 426570
        Entre Ríos 379293
        Santa Fe 829210



        Córdoba 929726
        Mendoza 521526
        San Luis 126661
        Misiones 388375
        Formosa 209713
        Buenos Aires 4373418
        Santiago del Estero 287842
        Ciudad de Buenos Aires 805251
        Catamarca 131805
        La Rioja 113383
        Santa Fe 829210


Se ve claramente que el servidor repartió el trabajo entre los dos clientes. Esta es la idea de Map-Reduce


Flag Counter