Implementar una función UDF de Apache Pig

0
13315

Implementar una UDF de Apache Pig

0. Índice de contenidos.


1. Introducción.

Este tutorial es una continuación del de primeros pasos con Apache Pig donde vamos a ver cómo crear una función UDF (User-Defined Function) de Pig para extender la funcionalidad que viene por defecto.

Las UDFs de Pig se pueden escribir en Java, Javascript, Jython, Python, Ruby y Groovy. Una librería que contiene un gran variedad de UDFs es la de piggybank. Contiene funciones para manejar fechas, operaciones matemáticas, estadísticas, manejo de strings, etc.

Si el tutorial de primeros pasos de Apache Pig se te quedó corto para afrontar algún cálculo más complejo, a continuación vamos a ver uno de los aspectos más interesentes de esta utilidad.

Puedes descargarte el código del tutorial desde mi repositorio de github pinchando aquí.

2. Entorno.

El tutorial se ha realizado con el siguiente entorno:

  • Ubuntu 12.04 64 bits
  • Oracle Java SDK 1.6.0_27
  • Apache Hadoop 2.2.0
  • Apache Pig 0.12.0

3. Crear la UDF

Para crear una User-Defined Function de Pig podemos hacerlo en varios lenguajes. Yo lo haré en Java por lo primeramente crearé un proyecto maven. En el pom.xml añadimos las dependencias de Hadoop y Pig.

<project xmlns="http://maven.apache.org/POM/4.0.0" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.autentia.tutoriales</groupId>
	<artifactId>pig-udf</artifactId>
	<version>1.0-SNAPSHOT</version>
	<packaging>jar</packaging>

	<name>pig-udf</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>

	<build>
		<plugins>
			<plugin>
				<groupId>org.apache.maven.plugins</groupId>
				<artifactId>maven-compiler-plugin</artifactId>
				<configuration>
					<encoding>${project.build.sourceEncoding}</encoding>
					<source>1.6</source>
					<target>1.6</target>
				</configuration>
			</plugin>
		</plugins>
	</build>

	<dependencies>
		<dependency>
			<groupId>org.apache.hadoop</groupId>
			<artifactId>hadoop-common</artifactId>
			<version>2.2.0</version>
		</dependency>

		<dependency>
			<groupId>org.apache.hadoop</groupId>
			<artifactId>hadoop-client</artifactId>
			<version>2.2.0</version>
		</dependency>

		<dependency>
			<groupId>org.apache.pig</groupId>
			<artifactId>pig</artifactId>
			<version>0.12.0</version>
		</dependency>
	</dependencies>
</project>

Una vez que tenemos la estructura del proyecto Maven creada creamos la clase de la UDF. ésta debe extender la clase org.apache.pig.EvalFunc e implementar el método exec. Este método será el que llame Pig cuando en el script indiquemos la UDF a utilizar.

Voy a utilizar el mismo ejemplo del tutorial de primeros pasos con Apache Pig. En este script sacábamos el valor medio de las medidas tomadas en el fichero. Pig era el encargado de calcular la media y nos devolvía el valor en decimal con varios decimales. Vamos a hacer una función para redondear a 2 decimales.

package com.autentia.tutoriales;

import java.io.IOException;

import org.apache.pig.EvalFunc;
import org.apache.pig.data.Tuple;

public class DecimalFormat extends EvalFunc<String> {

	public String exec(Tuple input) throws IOException {
		if (null == input || input.size() != 1) {
			return null;
		}

		final Double number = (Double) input.get(0);

		try {
			return new java.text.DecimalFormat("#.##").format(input.get(0));
		} catch (Exception e) {
			return String.valueOf(number);
		}
	}
}

4. Usar la UDF desde el script de Pig

Ahora vamos a hacer carga de la librería y usar la UDF que acabamos de crear. Antes de nada empaquetamos en un jar la clase con mvn package. En el script hacemos la carga de la librería con el comando register. A continuación creamos un alias para la función DecimalFormat. En la línea 17 cuando se calcula la media del valor se le pasa a la función DecimalFormat que la formateará a 2 decimales devolviendo el resultado que posteriormente se guardará en la salida:

-- Registramos la librería de la UDF
register 'target/pig-udf-1.0-SNAPSHOT.jar';

-- Alias para la UDF
define DecimalFormat com.autentia.tutoriales.DecimalFormat();

-- Hacemos la carga del fichero separando por ';' y creamos el schema.
measure = load 'input/calidad_del_aire_cyl_1997_2013.csv' using PigStorage(';') as (date:chararray, co:float, no:float, no2:float, o3:float, pm10:float, sh2:float, pm25:float, pst:float, so2:float, province:chararray, station:chararray);

-- Filtramos los resultados, la primera línea no nos vale.
filter_measure = filter measure by date != 'DIA';

-- Agrupamos los datos por provincia.
measure_by_province = group filter_measure by province;

-- Recorremos los registros por provincia y calculamos la media de co.
num_measures_by_province = foreach measure_by_province generate group, DecimalFormat(AVG(filter_measure.co)) as measure;

-- Ordenamos de menor a mayor índice de co.
ordered_measures = order num_measures_by_province by measure;

-- Almacenamos la salida en un fichero
store ordered_measures INTO 'output/measures_by_province.out';

Si lanzamos el script podemos observar el resultado

pig -x local -f udf.pig
SORIA		0.18
VALLADOLID	0.69
ZAMORA		0.84
BURGOS		0.86
ÁVILA		0.96
LEÓN		0.98
SEGOVIA		1.02
PALENCIA	1.18
SALAMANCA	1.39

6. Conclusiones.

Una buena herramienta de software es aquella que te permite multitud de opciones para desarrollar tu código pero es incluso mejor si no está cerrada sino que permite extenderla y enriquecerla con librerías personalizadas. En este tutorial hemos visto cómo crear una UDF para extender la funcionalidad de Apache Pig de una forma muy sencilla.

Si no tienes bastante con la funcionalidad por defecto que viene con la distribución de Apache Pig existen librerías de UDFs ya implementadas con multitud de funciones:

Puedes descargarte el código del tutorial desde mi repositorio de github pinchando aquí.

Espero que te haya sido de ayuda.

Un saludo.

Juan

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad