Descargando e instalando Pig
Algunos links de interés:
- Página web oficial: https://pig.apache.org/
- URL de releases: http://apache.rediris.es/pig/
- Pig Latin reference:http://pig.apache.org/docs/r0.7.0/piglatin_ref2.html
Lo primero será descargar, extraer Pig y decirle donde está la instalación de Hadoop (ver tutorial Instalando Hadoop en modo pseudo-distribuido (esto no es estrictamente necesario en el modo local pero nos ahorrará tiempo y quebraderos de cabeza en el futuro):
wget 'http://apache.rediris.es/pig/pig-0.12.1/pig-0.12.1.tar.gz' tar -zxvf pig-0.12.1.tar.gz cd pig-0.12.1/bin export PIG_CLASSPATH=$HADOOP_INSTALL
Bien, ahora vamos a hacer el mismo contador de palabras del tutorial anterior pero con Pig, para eso vamos a descargar el mismo archivo en formato de texto plano http://www.gutenberg.org/ebooks/11101 y lo vamos a poner en la carpeta bin dentro de Pig. Deberíamos tener los siguientes ficheros dentro de la carpeta de Pig:
total 204K
-rwxr-xr-x 1 fedora fedora 13K abr 5 10:43 pig
-rw-r--r-- 1 fedora fedora 161K abr 19 23:51 pg11101.txt
-rwxr-xr-x 1 fedora fedora 5,6K abr 5 10:43 pig.cmd
-rwxr-xr-x 1 fedora fedora 14K abr 5 10:43 pig.py
/home/fedora/Descargas/pig-0.12.1/bin
[fedora@localhost bin]$
Ejecutando Pig en modo local
pig -x local
Despues de unos cuantos mensajes de log aparece grunt
grunt>
Ahora vamos a escribir el contador de palabras en Pig, lo primero será cargar el archivo con la instrucción LOAD:
grunt>myfile = LOAD 'pg11101.txt' AS (words:chararray);
Si usamos la instrucción DUMP para ver los contenidos de la variable myfile, podemos ver la estructura general que tiene ahora cada linea:
grunt>DUMP myfile;
...
(EBooks posted since November 2003, with etext numbers OVER #10000, are)
(filed in a different way. The year of a release date is no longer part)
(of the directory path. The path is based on the etext number (which is)
...
Todavía falta bastante, ni siquiera tenemos una lista de palabras. Para poder separarlo por palabras, podemos usar la instrucción TOKENIZE:
grunt> wordsList = FOREACH myfile GENERATE TOKENIZE($0);
...
({(EBooks),(posted),(since),(November),(2003),(with),(etext),(numbers),(OVER),(#10000),(are)})
({(filed),(in),(a),(different),(way.),(The),(year),(of),(a),(release),(date),(is),(no),(longer),(part)})
({(of),(the),(directory),(path.),(The),(path),(is),(based),(on),(the),(etext),(number),(which),(is)})
...
Si nos fijamos bien, ahora tenemos tuplas (arrays) de palabras pero seguimos sin tener un listado de palabras separadas: Para conseguir dicho listado, tenemos la instrucción FLATTEN:
grunt>words = FOREACH wordsList GENERATE FLATTEN($0);
...
(at:)
()
(http://www.gutenberg.net/1/0/2/3/10234)
()
(or)
(filename)
(24689)
(would)
(be)como
(found)
(at:)
...
Con lo que ahora tenemos las listas separadas, una palabra por linea (aunque todavía están repetidas). Ahora es el momento de agruparlas usando la instrucción GROUP:
grunt>groupedWords = GROUP words BY $0;
...
(www.gutenberg.net,{(www.gutenberg.net),(www.gutenberg.net),(www.gutenberg.net)})
(Constantinopolitan,{(Constantinopolitan),(Constantinopolitan)})
...
La cosa marcha, ahora tenemos listados agrupados de la misma palabra por cada línea. Sólo nos falta contar cuantas ocurrencias hay por línea. Para ello le diremos que por cada linea nos tiene que crear una nueva pareja clave/valor que clave ($0) siga siendo el nombre de la palabra que estamos contando, como hasta ahora y el valor la cuenta de ítems en la segunda posición ($1) con la instrucción COUNT.
grunt>final = FOREACH groupedWords GENERATE $0, COUNT($1);
...
(www.gutenberg.net,3)
(Constantinopolitan,2)
...
Y ahí lo tenemos, nuestro conteo de palabras.
Bonus: Ordenando ocurrencias en Pig
Y como extra, vamos a ordenar el resultado del conteo de palabras en orden descendente, de tal manera que el último de los resultados de la lista sea la palabra mas usada de todo el texto:
grunt>sortedWords = ORDER final BY $1 ASC;
...
(a,697)
(in,833)
(and,1137)
(of,1323)
(the,2047)
...
Por fin, parece que nuestro ganador es la palabra "the". Espero que el tutorial haya resulado interesante :)