Fusión de datos de dinosaurios con Hadoop

HadoopBeginner
Practicar Ahora

Introducción

En la era de los dinosaurios, un valiente cazador de dinosaurios llamado Alex emprende una emocionante misión para descubrir los secretos de estas criaturas prehistóricas. El objetivo de Alex es recopilar datos valiosos de diversas fuentes y realizar un análisis avanzado para obtener información sobre el comportamiento, la dieta y la evolución de diferentes especies de dinosaurios.

Para lograr esto, Alex necesita aprovechar el poder de Hadoop MapReduce y su capacidad para realizar operaciones de unión de manera eficiente. Al unir datos de múltiples fuentes, Alex puede combinar información sobre fósiles de dinosaurios, sus ubicaciones geológicas y condiciones ambientales para crear un panorama completo del mundo de los dinosaurios.

Configurar el entorno y los datos

En este paso, configuraremos el entorno necesario y prepararemos los datos para la operación de unión.

Primero, cambie al usuario hadoop y luego cambie al directorio principal del usuario hadoop:

su - hadoop

Cree un nuevo directorio llamado join-lab para almacenar nuestros archivos:

mkdir join-lab
cd join-lab

A continuación, creemos dos archivos de datos: dinosaurs.txt y locations.txt. Estos archivos contendrán información sobre los dinosaurios y sus ubicaciones fósiles, respectivamente.

Cree dinosaurs.txt con el siguiente contenido:

trex,Tyrannosaurus Rex,carnívoro
velociraptor,Velociraptor,carnívoro
brachiosaurus,Brachiosaurus,herbívoro
stegosaurus,Stegosaurus,herbívoro

Cree locations.txt con el siguiente contenido:

trex,América del Norte
velociraptor,Asia
brachiosaurus, África
stegosaurus,América del Norte

Finalmente, cargue join-lab a hdfs usando el siguiente comando:

hadoop fs -mkdir -p /home/hadoop
hadoop fs -put /home/hadoop/join-lab /home/hadoop/

Implementar la operación de unión

En este paso, implementaremos un trabajo MapReduce para realizar una operación de unión en los archivos dinosaurs.txt y locations.txt.

Cree un nuevo archivo Java llamado JoinDinosaurs.java en el directorio /home/hadoop/join-lab con el siguiente contenido:

import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.Reducer;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.input.TextInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class JoinDinosaurs {

    public static class JoinMapper extends Mapper<LongWritable, Text, Text, Text> {
        private final Text outKey = new Text();
        private final Text outValue = new Text();

        @Override
        protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
            String line = value.toString();
            String[] parts = line.split(",");

            if (parts.length == 2) { // locations.txt
                outKey.set(parts[0]);
                outValue.set("LOC:" + parts[1]);
            } else if (parts.length == 3) { // dinosaurs.txt
                outKey.set(parts[0]);
                outValue.set("DIN:" + parts[1] + "," + parts[2]);
            }

            context.write(outKey, outValue);
        }
    }

    public static class JoinReducer extends Reducer<Text, Text, Text, Text> {
        private final Text outValue = new Text();

        @Override
        protected void reduce(Text key, Iterable<Text> values, Context context) throws IOException, InterruptedException {
            Map<String, String> dinMap = new HashMap<>();
            StringBuilder locBuilder = new StringBuilder();

            for (Text value : values) {
                String valStr = value.toString();
                if (valStr.startsWith("DIN:")) {
                    dinMap.put("DIN", valStr.substring(4));
                } else if (valStr.startsWith("LOC:")) {
                    locBuilder.append(valStr.substring(4)).append(",");
                }

                if (locBuilder.length() > 0) {
                    locBuilder.deleteCharAt(locBuilder.length() - 1);
                }
            }

            StringBuilder outBuilder = new StringBuilder();
            for (Map.Entry<String, String> entry : dinMap.entrySet()) {
                outBuilder.append(entry.getValue()).append("\t").append(locBuilder.toString().trim());
            }

            outValue.set(outBuilder.toString());
            context.write(key, outValue);
        }
    }

    public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException {
        if (args.length!= 2) {
            System.err.println("Usage: JoinDinosaurs <input_dir> <output_dir>");
            System.exit(1);
        }

        Job job = Job.getInstance();
        job.setJarByClass(JoinDinosaurs.class);
        job.setJobName("Join Dinosaurs");

        FileInputFormat.addInputPath(job, new Path(args[0]));
        FileOutputFormat.setOutputPath(job, new Path(args[1]));

        job.setMapperClass(JoinMapper.class);
        job.setReducerClass(JoinReducer.class);

        job.setInputFormatClass(TextInputFormat.class);
        job.setOutputFormatClass(TextOutputFormat.class);

        job.setOutputKeyClass(Text.class);
        job.setOutputValueClass(Text.class);

        System.exit(job.waitForCompletion(true)? 0 : 1);
    }
}

Este código define un trabajo MapReduce con un JoinMapper y un JoinReducer personalizados. El mapper lee los datos de entrada de dinosaurs.txt y locations.txt y emite pares clave-valor con el nombre del dinosaurio como clave y el tipo de datos ("DIN" o "LOC") junto con el valor correspondiente. El reducer luego realiza la operación de unión agrupando los valores por clave y combinando la información del dinosaurio con la ubicación.

Para compilar el código, ejecute el siguiente comando:

mkdir classes
javac -source 8 -target 8 -cp "/home/hadoop/hadoop/share/hadoop/common/hadoop-common-3.3.6.jar:/home/hadoop/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-client-core-3.3.6.jar:/home/hadoop/hadoop/share/hadoop/common/lib/*" -d classes JoinDinosaurs.java
jar -cvf join-dinosaurs.jar -C classes/.

A continuación, ejecute el trabajo MapReduce usando el siguiente comando:

hadoop jar join-dinosaurs.jar JoinDinosaurs /home/hadoop/join-lab /home/hadoop/join-lab/output

Este comando ejecuta la clase JoinDinosaurs del archivo join-dinosaurs.jar, con el directorio de entrada /home/hadoop/join-lab (que contiene dinosaurs.txt y locations.txt) y el directorio de salida /home/hadoop/join-lab/output.

Después de que el trabajo se complete con éxito, puede ver la salida en el directorio /home/hadoop/join-lab/output.

Analizar la salida

En este paso, analizaremos la salida de la operación de unión para obtener información sobre el mundo de los dinosaurios.

Primero, veamos el contenido del directorio de salida:

hadoop fs -ls /home/hadoop/join-lab/output
hadoop fs -cat /home/hadoop/join-lab/output/part-r-00000

Debería ver una salida similar a la siguiente:

brachiosaurus    Brachiosaurus,herbívoro    África
stegosaurus      Stegosaurus,herbívoro      América del Norte
trex     Tyrannosaurus Rex,carnívoro        América del Norte
velociraptor     Velociraptor,carnívoro     Asia

Esta salida muestra los datos unidos, con cada línea que contiene el nombre del dinosaurio, sus detalles (especie y dieta) y la ubicación donde se encontraron sus fósiles.

Basados en la salida, podemos hacer las siguientes observaciones:

  • El Tyrannosaurus Rex (T-Rex) y el Velociraptor eran dinosaurios carnívoros, mientras que el Brachiosaurus y el Stegosaurus eran herbívoros.
  • Los fósiles del Brachiosaurus se encontraron en África, los fósiles del Stegosaurus y el Tyrannosaurus Rex se encontraron en América del Norte, y los fósiles del Velociraptor se encontraron en Asia.

Estas informaciones pueden ayudar a los paleontólogos a entender mejor la distribución, el comportamiento y la evolución de diferentes especies de dinosaurios en diferentes regiones geológicas.

Resumen

En este laboratorio, exploramos la implementación de una operación de unión utilizando Hadoop MapReduce. Al combinar datos de múltiples fuentes, pudimos obtener información valiosa sobre el mundo de los dinosaurios, incluyendo sus especies, dietas y ubicaciones fósiles.

El laboratorio presentó el concepto de unir datos utilizando MapReduce, donde el mapper prepara los datos para la operación de unión y el reducer realiza la unión real agrupando los valores por clave y combinando la información.

A través de la experiencia práctica de configurar el entorno, preparar los datos, implementar el trabajo MapReduce y analizar la salida, adquirimos conocimiento práctico sobre cómo aprovechar las poderosas capacidades de procesamiento de datos de Hadoop para resolver problemas analíticos complejos.

Este laboratorio no solo fortaleció nuestra comprensión de las operaciones de unión, sino que también reforzó nuestras habilidades en trabajar con Hadoop MapReduce, escribir código Java y ejecutar comandos en un entorno Linux. La experiencia de diseñar e implementar una solución completa desde cero fue invaluable y sin duda contribuirá a nuestro crecimiento como ingenieros de datos o científicos de datos.