La creación de un modelo de machine learning implica la recopilación y preparación de datos, la selección de un algoritmo adecuado, el entrenamiento del modelo con los datos preparados y la evaluación de su rendimiento mediante pruebas e iteraciones.
Datos de entrenamiento
El proceso de machine learning comienza con la recopilación y el procesamiento de los datos de entrenamiento. Los datos de mala calidad suelen denominarse basura que entra y basura que sale, por lo que un modelo de machine learning es tan bueno como los datos que se utilizan para entrenarlo. Si bien la preparación y el procesamiento de los datos a veces son un proceso rutinario, podría decirse que es la etapa más crítica para hacer que todo el modelo funcione según lo previsto o perjudicar su rendimiento.
Hay varios tipos diferentes de datos que se utilizan para entrenar un modelo de ML. En primer lugar, es importante conocer la diferencia entre los datos etiquetados y los no etiquetados.
NoteDatos etiquetados
Los datos etiquetados son un conjunto de datos en el que cada instancia o ejemplo va acompañado de una etiqueta o variable de destino que representa el resultado o la clasificación que se espera. Por lo general, estas etiquetas las proporcionan expertos humanos o se obtienen mediante un proceso confiable.
Ejemplo: En una tarea de clasificación de imágenes, los datos etiquetados consistirían en imágenes junto con sus etiquetas de clase correspondientes (por ejemplo, gato, perro, automóvil).
NoteDatos sin etiquetar
Los datos sin etiquetar son un conjunto de datos en el que las instancias o los ejemplos no tienen etiquetas ni variables de destino asociadas. Los datos se componen únicamente de características de entrada, sin ningún resultado ni una clasificación correspondiente.
Ejemplo: una recopilación de imágenes sin etiquetas ni anotaciones.
Los principales tipos de datos que se utilizan en el entrenamiento son los datos estructurados y no estructurados. Existen varios subtipos, que se pueden ver al expandir las siguientes categorías.
NoteDatos estructurados
Los datos estructurados se refieren a los datos que están organizados y tienen un formato predefinido, normalmente en forma de tablas o bases de datos con filas y columnas. Este tipo de datos es adecuado para los algoritmos tradicionales de machine learning que requieren características y etiquetas bien definidas. A continuación, se detallan los tipos de datos estructurados.
Datos tabulares: Esto incluye los datos almacenados en hojas de cálculo, bases de datos o archivos CSV, con filas que representan instancias y columnas que representan características o atributos.
Datos de series temporales: Este tipo de datos consiste en secuencias de valores que se miden en puntos sucesivos en el tiempo, como los precios de las acciones, las lecturas de los sensores o los datos meteorológicos.
NoteDatos no estructurados
Los datos no estructurados son aquellos que carecen de una estructura o formato predefinidos, como texto, imágenes, audio y video. Este tipo de datos requiere técnicas de machine learning más avanzadas para extraer patrones e información significativos.
Datos de texto: Esto incluye documentos, artículos, publicaciones en redes sociales y otros datos textuales.
Datos de imagen: Esto incluye imágenes digitales, fotografías y fotogramas de video.
Proceso de Machine Learning
Los datos de entrenamiento compilados se cargan en algoritmos de machine learning. El proceso de ML se divide tradicionalmente en tres categorías amplias: el aprendizaje supervisado, el aprendizajeno supervisado y el aprendizaje por refuerzo.
En el aprendizaje supervisado, los algoritmos se entrenan con datos etiquetados. El objetivo es aprender una función de mapeo que pueda predecir el resultado de nuevos datos de entrada no vistos.
El aprendizaje no supervisado se refiere a los algoritmos que aprenden a partir de datos no etiquetados. El objetivo es descubrir patrones, estructuras o relaciones inherentes dentro de los datos de entrada.
En el aprendizaje por refuerzo, la máquina solo recibe una puntuación de rendimiento como guía; en el aprendizaje semisupervisado, solo se etiqueta una parte de los datos de entrenamiento. La retroalimentación se hace en forma de recompensas o penalizaciones por las acciones de la máquina y esta aprende de estos comentarios para mejorar las decisiones que toma con el paso del tiempo.
Conjunto de entrenamiento y conjunto de test
El esquema muestra cómo se divide un conjunto de datos (Dataset) en Machine Learning para entrenar y evaluar los modelos correctamente. Se divide en tres enfoques principales:
Holdout Method (Método de validación simple): El dataset completo se divide en dos partes. Un bloque grande se usa para Training (entrenar el modelo) y un bloque más pequeño se reserva para Testing (probar su rendimiento con datos que no ha visto).
Cross Validation (Validación cruzada): El conjunto de entrenamiento se subdivide en múltiples bloques o particiones iguales. El modelo se entrena y valida varias veces turnando estos bloques para asegurar que la evaluación sea robusta y no dependa de un solo corte de datos.
Training, Validation, Testing (Tres particiones): Cuando se dispone de suficientes datos (Data Permitting), el dataset se divide en tres partes:
Training: Para ajustar los parámetros del modelo.
Validation: Para ajustar hiperparámetros y tomar decisiones sobre la arquitectura durante el desarrollo.
Testing: Como evaluación final y completamente independiente para medir la eficacia real del modelo.
Sesgo (bias) y varianza
Sobreajuste u “overfitting”
Explicar el conjunto de datos de entrenamiento, en lugar de encontrar patrones que generalizan. El modelo se ajusta bien al conjunto de datos de entrenamiento pero falla en el conjunto de datos de test.
Validación cruzada
El proceso básico:
El conjunto de datos total (Data) se divide en k partes iguales o “pliegues” (folds), en este caso 5 (Fold 1 al Fold 5).
El modelo se entrena y se prueba k veces. En cada iteración, se usa un bloque diferente como conjunto de prueba (Test) y los k−1 bloques restantes como conjunto de entrenamiento (Training). Por ejemplo, en el Fold 1 la primera sección es para prueba y las cuatro siguientes para entrenar; en el Fold 2 la sección de prueba se desplaza al segundo bloque, y así sucesivamente.
Cálculo del rendimiento: Los resultados de las métricas de evaluación de cada uno de los 5 modelos se combinan calculando su promedio (Average), lo que arroja una medida final de desempeño mucho más sólida y confiable (Final Measure of Performance).
Ventajas:
Permite que cada muestra o registro de datos se utilice tanto para entrenar como para probar en diferentes momentos, aprovechando al máximo la información disponible.
Es el método estándar para estimar qué tan bien generaliza un modelo ante datos nuevos o no vistos.
¿Qué son los árboles de decisión?
El enfoque classification and regression tree (CART) fue desarrollado por Breiman et al. (1984).
Son un tipo de algoritmos de aprendizaje supervisado (i.e., existe una variable objetivo predefinida).
Principalmente usados en problemas de clasificación.
Las variables de entrada y salida pueden ser categóricas o continuas.
Divide el espacio de predictores (variables independientes) en regiones distintas y no sobrepuestas.
Selecciona varaibles explicativas (predictivas) que son mas discriminantes para la variable respuesta. Construye una regla de decisión que permite asignar un nuevo individuo a una clase de la variable de interés.
Ventajas
A diferencia de modelos estadísticos más restrictivos (como la regresión lineal), los árboles no requieren que transformes las variables continuas en discretas ni que codifiques obligatoriamente las categóricas mediante trucos complejos. El algoritmo maneja de forma natural variables numéricas, ordinales y nominales simultáneamente.
Su estructura en forma de diagrama de flujo hace que la lógica del modelo sea completamente transparente. Esto facilita enormemente la interpretación de los resultados y permite explicárselos a personas sin formación técnica.
Durante su construcción, el algoritmo evalúa todas las variables predictoras disponibles y selecciona por sí mismo cuáles son las más informativas para dividir los datos en cada nodo. Las variables que no aportan valor predictivo simplemente se ignoran o se colocan en niveles inferiores, lo que ayuda a filtrar el ruido sin necesidad de que hagas un análisis de correlación o selección manual previo.
Desventajas
Los árboles de decisión se construyen mediante algoritmos voraces (greedy) que seleccionan el mejor corte local en cada nodo de manera secuencial. Si cambias, añades o eliminas unas pocas observaciones en el conjunto de entrenamiento, el corte inicial puede cambiar por completo, provocando un efecto cascada que altera drásticamente toda la estructura del árbol y sus reglas de predicción.
Encontrar el árbol perfecto (el que minimice el error global con la estructura más simple) es un problema computacionalmente intratable (NP-completo) debido a la enorme cantidad de combinaciones posibles de variables y puntos de corte. Por esta razón, los algoritmos se basan en optimizaciones locales paso a paso que no garantizan llegar al mejor árbol global, requiriendo métodos posteriores como la poda (pruning).
A medida que un árbol se vuelve más profundo, los datos se van fragmentando en subconjuntos cada vez más reducidos en cada bifurcación. Si el dataset total es pequeño, los nodos terminales (hojas) terminarán con muy pocas observaciones, lo que genera estimaciones estadísticas poco confiables, alta varianza y una propensión severa al sobreajuste (overfitting).
Ejemplo 1.
El departamento de analítica de una empresa de comercio electrónico desea diseñar una campaña de marketing personalizada para optimizar el uso de cupones de descuento. Para lograrlo, el equipo de ciencia de datos ha extraído una muestra de clientes con el fin de estudiar qué perfiles son más propensos a utilizarlos.
Se cuenta con un conjunto de datos sintético que registra tres variables por cada cliente:
Edad: Variable cuantitativa continua que representa la edad del cliente.
Ingresos: Variable cuantitativa continua que indica los ingresos anuales del cliente.
Usa Descuento: Variable cualitativa binaria con etiquetas "Sí" o "No", que indica si el cliente históricamente aprovecha los descuentos.
¿Qué variable es la más significativa para la mejor división de la población?
head(datos_clientes)
# A tibble: 6 × 4
id edad ingresos descuento
<int> <dbl> <dbl> <chr>
1 1 54 44512 No
2 2 34 26381 Sí
3 3 44 59006 Sí
4 4 46 41716 No
5 5 44 39386 No
6 6 39 30141 No
ggplot(datos_clientes, aes(x = edad, y = ingresos, color = descuento)) +geom_point(size =3, alpha =0.8) +labs(title ="Distribución de Clientes por Edad e Ingresos",subtitle ="Conjunto de datos sintético",x ="Edad",y ="Ingresos",color ="¿Usa Descuento?" ) +theme_minimal() +scale_color_manual(values =c("Sí"="#2b5c8f", "No"="#e07a5f"))
¿Qué es un nodo puro?
Un nodo es completamente puro cuando todos los elementos que contiene pertenecen a una sola categoría (clase). Por ejemplo, si en una de las cajas finales del árbol (hojas) todos los clientes son "Sí", ese nodo tiene una pureza del 100% porque no hay mezcla.
¿Qué es un nodo impuro?
Un nodo es impuro cuando hay una mezcla de diferentes clases. Por ejemplo, el nodo raíz (el inicio del árbol) tiene una mezcla de clientes que usan descuento y otros que no. Esa es una alta impureza.
¿Cómo funciona el algoritmo?
El algoritmo de particionamiento recursivo (greedy) evalúa todas las posibles variables (como Edad o Ingresos) y todos los puntos de corte posibles. Su objetivo en cada paso es encontrar el umbral de corte que reduzca al máximo la impureza, logrando que los grupos resultantes (los nodos hijos) queden lo más “limpios” o separados posibles entre clases.
No
Sí 0
No 1
rpart.plot( modelo_arbol, digits =-4, # Positivo para mostrar decimales correctos (ej. 3 decimales)type =2,extra =104, # Muestra la clase predicha, n y las probabilidades de cada clasebox.palette ="RdYlGn", fallen.leaves =TRUE, branch.lty =3, main ="Modelo de Árbol de Decisión: Predicción de Descuento")
tally(~ descuento, format ="proportion", data = datos_clientes)
descuento
Sí No
0.3133333 0.6866667
1. Nodo Raíz
Contenido: Muestra que el total de la base de datos está compuesto por un 31.33% de clientes que sí usan descuento y un 68.67% que no, lo cual coincide exactamente con la proporción global calculada con tally().
Primer corte: El algoritmo evalúa la variable Ingresos con un umbral de 51,962.
2. Rama Izquierda (Clientes con Ingresos \ge 51,962)
Representa: El 26.00% de los clientes totales del dataset. En este grupo, la probabilidad inicial de usar descuento es alta (79.49%).
Segundo corte: Evalúa la Edad con un umbral de 34 años (edad >= 34).
Hojas terminales:
Si el cliente tiene 34 años o más (20.67% de los datos), el árbol predice Sí con una probabilidad del 100%.
Si el cliente es menor de 34 años (5.33% de los datos), el árbol predice No con una probabilidad del 100%.
3. Rama Derecha (Clientes con Ingresos < 51,962)
Representa: El 74.00% de los clientes restantes. Aquí la mayoría no usa descuento (85.59% de probabilidad de “No”).
Siguientes cortes: El algoritmo realiza divisiones adicionales evaluando la edad (edad < 35) y un nuevo umbral de ingresos (ingresos < 39510).
Hojas terminales (abajo a la derecha):
Un subgrupo con ingresos menores a 39,510 y ciertas condiciones de edad se clasifica como Sí (8.67% del total).
Los demás grupos se clasifican como No, abarcando el 12.67% y el 52.67% de los datos respectivamente.
¿Cómo funciona Árboles de decisión?
Paso 1. Preparación inicial y limpieza de los datos:
Como en cualquier modelo supervisado, el primer paso es asegurar que los datos estén en condiciones adecuadas:
Cargar los datos: importa el conjunto de datos y asegúrate de identificar correctamente la variable respuesta y las variables predictoras.
Explorar los datos: analiza la distribución de las clases, la presencia de valores atípicos, datos faltantes o categorías con muy pocas observaciones.
Codificar variables categóricas: aunque algunos algoritmos pueden manejar variables categóricas directamente, es buena práctica revisar la codificación.
En esta etapa también puedes realizar análisis exploratorio para entender qué variables podrían tener mayor relación con la variable respuesta.
Paso 2: Dividir los datos en conjunto de entrenamiento y prueba:
Divide el conjunto total en dos subconjuntos de forma aleatoria:
Un conjunto de entrenamiento (aproximadamente 70-80%), que se usa para ajustar el modelo.
Un conjunto de prueba (20-30%) que no se usará en la construcción inicial del modelo y servirá para evaluar el desempeño del mismo.
Una división adecuada permite evaluar la capacidad predictiva real del árbol, evitando un sobreajuste (overfitting). La división del conjunto de datos en entrenamiento y prueba puede realizarse fácilmente en R utilizando la función createFolds() del paquete caret, que permite crear particiones aleatorias y balanceadas de los datos.
Paso 3: Construcción del árbol de decisión:
En un árbol de decisión se encuentran los siguientes componentes:
Nodos: son las variables de entrada.
Ramas: representan los posibles valores de las variables de entrada.
Hojas: son los posibles valores de la variable de salida.
Como primer elemento de un árbol de decisión tenemos el nodo raíz que va a representar la variable de mayor relevancia en el proceso de clasificación.
Método CART
De manera general, lo que hace este algoritmo es encontrar la variable independiente que mejor separa nuestros datos en grupos. Esta mejor separación es expresada con una regla. A cada regla corresponde un nodo.
Una vez hecho esto, los datos son separados (particionados) en grupos a partir de la regla obtenida. Después, para cada uno de los grupos resultantes, repite el mismo proceso. Se busca la variable que mejor separa los datos en grupos, se obtiene una regla, y se separan los datos. Hacemos esto de manera recursiva hasta que nos es imposible obtener una mejor separación. Cuando esto ocurre, el algoritmo se detiene. Cuando un grupo no puede ser partido mejor, se le llama nodo terminal u hoja.
Una característica muy importante en este algoritmo es que una vez que alguna variable ha sido elegida para separar los datos, ya no es usada de nuevo en los grupos que ha creado. Se buscan variables distintas que mejoren la separación de los datos.
En R, se encuentra programado en la librería rpart() . También se encuentra programado la visualización del árbol, en la librería rpart.plot() .
Paso 4: Validar la estabilidad del modelo
Para validar el modelo se usa Validación Cruzada (K-fold Cross-validation) Ahora, realiza una validación cruzada K-fold para comprobar la estabilidad del modelo. La forma más usual que se hace es:
Divide tu conjunto de entrenamiento en k grupos.
Entrena el modelo en K−1 grupos y prueba en el restante.
Repite el proceso hasta que cada grupo haya sido usado para prueba exactamente una vez.
Calcula el rendimiento promedio en términos de las métricas anteriores.
Paso 5: Interpretación de los resultados finales:
Finalmente, se analizan tanto el rendimiento como la estructura del árbol:
Matriz de confusión promedio obtenida por la validación cruzada.
Indicadores de desempeño promedio: exactitud, sensibilidad, especificidad, etc.
Dividir los datos en conjunto de entrenamiento y prueba
Mediante un muestreo aleatorio, separamos el conjunto de entrenamiento y en conjunto de prueba. Supongamos en 5 grupos, 4 para entrenamiento y 1 para prueba.
set.seed(2025)library(caret)
Warning: package 'caret' was built under R version 4.6.2
Adjuntando el paquete: 'caret'
The following object is masked from 'package:mosaic':
dotPlot
The following object is masked from 'package:purrr':
lift
folds <-createFolds(iris$Species, k =5)entrenamiento <- iris[-folds[[5]],]prueba <- iris[folds[[5]],]
set.seed(2025): Fija una “semilla” para el generador de números pseudoaleatorios. Como la selección de los datos para cada grupo es aleatoria, fijar un número (en este caso 2025) garantiza que cada vez que corras el código obtengas exactamente la misma partición de datos, asegurando la reproducibilidad de tu trabajo.
library(caret): Carga el paquete caret (Classification And Regression Training), que es una de las herramientas más utilizadas en R para aprendizaje automático y que contiene la función para crear particiones.
folds <- createFolds(iris$Species, k = 5): Divide los índices de las filas del conjunto de datos iris en 5 grupos (folds) iguales o de tamaño similar.
El parámetro estratificado (iris$Species): Al pasarle la columna de especies, la función se asegura de que cada uno de los 5 grupos mantenga la misma proporción de clases (especies de flores) que el dataset original, evitando que un grupo se quede sin alguna categoría.
entrenamiento <- iris[-folds[[5]], ]: Crea el conjunto de datos de entrenamiento. Utiliza el operador negativo [-] para excluir todos los índices que pertenecen al quinto grupo (folds[[5]]). Por lo tanto, toma los datos de los otros 4 grupos restantes (el 80% de los datos) para entrenar el modelo.
prueba <- iris[folds[[5]], ]: Crea el conjunto de datos de prueba (o validación). Selecciona únicamente los índices del quinto grupo (folds[[5]]) (el 20% restante de los datos) para evaluar qué tan bien generaliza el modelo con datos que no ha visto durante el entrenamiento.
Construimos el modelo ajustado con los datos de entrenamiento. Para este ejemplo utilizaremos el árbol CART.
library(rpart)modelo1 <-rpart(Species ~ ., data = entrenamiento, method ="class")modelo1
No se aplico en este ejemplo, pero se podría hacer la validación haciendo 5 replicas del proceso, tomando en cada iteración como conjunto de entrenamiento cada una de las particiones creadas.
Interpretación de los resultados finales
Podemos observar en la tabla, en las filas la clasificación real y en las columnas la predicción. La tasa de aciertos del modelo respecto a las observaciones de entrenamiento sería:
Podemos calcular la predicción para los datos de entrenamiento.
TA <-sum(diag(tt))/sum(tt) paste0("Tasa de aciertos con los datos de entrenamiento: ", round(TA,4)*100, "%", sep="")
[1] "Tasa de aciertos con los datos de entrenamiento: 96.67%"
Podemos hablar de una precisión de aproximadamente el 97%. Ahora, para analizar la calidad del modelo, veamos que tan buena es la predicción para el conjunto de prueba.
Pred <-predict(modelo1, prueba[,-5],type="class")table <-table(prueba[,5],Pred)table
TAP <-sum(diag(table))/sum(table) paste0("Tasa de aciertos con los datos de prueba: ", round(TAP,4)*100, "%", sep="")
[1] "Tasa de aciertos con los datos de prueba: 93.33%"
Encontramos que el modelo logra predecir aproximadamente un 93% los datos de prueba.
rpart.plot( modelo1, digits =-4, # Positivo para mostrar decimales correctos (ej. 3 decimales)type =2,extra =104, # Muestra la clase predicha, n y las probabilidades de cada clasebox.palette ="RdYlGn", fallen.leaves =TRUE, branch.lty =3, main ="Modelo de Árbol de Decisión: Predicción de Descuento")
No se aplico en este ejemplo, pero se podría hacer la validación haciendo 5 replicas del proceso, tomando en cada iteración como conjunto de entrenamiento cada una de las particiones creadas.
Interpretación de los resultados finales
Podemos observar en la tabla, en las filas la clasificación real y en las columnas la predicción. La tasa de aciertos del modelo respecto a las observaciones de entrenamiento sería:
Podemos calcular la predicción para los datos de entrenamiento.
pred Murio Sobrevive
Murio 307 63
Sobrevive 32 169
TA <-sum(diag(tt))/sum(tt) paste0("Tasa de aciertos con los datos de entrenamiento: ", round(TA,4)*100, "%", sep="")
[1] "Tasa de aciertos con los datos de entrenamiento: 83.36%"
Podemos hablar de una precisión de aproximadamente el 83.36%. Ahora, para analizar la calidad del modelo, veamos que tan buena es la predicción para el conjunto de prueba.
Pred <-predict(modelotitanic, pruebatitanic[,-4],type="class")table <-table(pruebatitanic[,4],Pred)table
Pred
Murio Sobrevive
Murio 72 13
Sobrevive 21 37
TAP <-sum(diag(table))/sum(table) paste0("Tasa de aciertos con los datos de prueba: ", round(TAP,4)*100, "%", sep="")
[1] "Tasa de aciertos con los datos de prueba: 76.22%"
Encontramos que el modelo logra predecir aproximadamente un 76% los datos de prueba.
rpart.plot( modelotitanic, digits =-4, # Positivo para mostrar decimales correctos (ej. 3 decimales)type =2,extra =104, # Muestra la clase predicha, n y las probabilidades de cada clasebox.palette ="RdYlGn", fallen.leaves =TRUE, branch.lty =3, main ="Modelo de Árbol de Decisión: Predicción de Descuento")
pruebatitanic
Pclass Age Sex Survived
3 3 26.00 female Sobrevive
23 3 15.00 female Sobrevive
25 3 8.00 female Murio
38 3 21.00 male Murio
42 2 27.00 female Murio
52 3 21.00 male Murio
61 3 22.00 male Murio
68 3 19.00 male Murio
73 2 21.00 male Murio
76 3 25.00 male Murio
82 3 29.00 male Sobrevive
84 1 28.00 male Murio
107 3 21.00 female Sobrevive
112 3 14.50 female Murio
114 3 20.00 female Murio
120 3 2.00 female Murio
124 2 32.50 female Sobrevive
125 1 54.00 male Murio
132 3 20.00 male Murio
135 2 25.00 male Murio
137 1 19.00 female Sobrevive
142 3 22.00 female Sobrevive
147 3 27.00 male Sobrevive
149 2 36.50 male Murio
150 2 42.00 male Murio
154 3 40.50 male Murio
156 1 51.00 male Murio
163 3 26.00 male Murio
166 3 9.00 male Sobrevive
171 1 61.00 male Murio
190 3 36.00 male Murio
198 3 42.00 male Murio
208 3 26.00 male Sobrevive
209 3 16.00 female Sobrevive
218 2 42.00 male Murio
220 2 30.00 male Murio
222 2 27.00 male Murio
223 3 51.00 male Murio
227 2 19.00 male Sobrevive
229 2 18.00 male Murio
235 2 24.00 male Murio
238 2 8.00 female Sobrevive
239 2 19.00 male Murio
243 2 29.00 male Murio
244 3 22.00 male Murio
250 2 54.00 male Murio
253 1 62.00 male Murio
254 3 30.00 male Murio
260 2 50.00 female Sobrevive
262 3 3.00 male Sobrevive
276 1 63.00 female Sobrevive
284 3 19.00 male Sobrevive
286 3 33.00 male Murio
289 2 42.00 male Sobrevive
294 3 24.00 female Murio
295 3 24.00 male Murio
311 1 24.00 female Sobrevive
328 2 36.00 female Sobrevive
334 3 16.00 male Murio
339 3 45.00 male Sobrevive
340 1 45.00 male Murio
344 2 25.00 male Murio
366 3 30.00 male Murio
370 1 24.00 female Sobrevive
371 1 25.00 male Sobrevive
379 3 20.00 male Murio
381 1 42.00 female Sobrevive
400 2 28.00 female Sobrevive
401 3 39.00 male Sobrevive
404 3 28.00 male Murio
405 3 20.00 female Murio
406 2 34.00 male Murio
423 3 29.00 male Murio
439 1 64.00 male Murio
454 1 49.00 male Sobrevive
456 3 29.00 male Sobrevive
461 1 48.00 male Sobrevive
462 3 34.00 male Murio
464 2 48.00 male Murio
468 1 56.00 male Murio
470 3 0.75 female Sobrevive
502 3 21.00 female Murio
509 3 28.00 male Murio
515 3 24.00 male Murio
517 2 34.00 female Sobrevive
519 2 36.00 female Sobrevive
522 3 22.00 male Murio
540 1 22.00 female Sobrevive
541 1 36.00 female Sobrevive
547 2 19.00 female Sobrevive
549 3 33.00 male Murio
559 1 39.00 female Sobrevive
563 2 28.00 male Murio
567 3 19.00 male Murio
568 3 29.00 female Murio
572 1 53.00 female Sobrevive
576 3 19.00 male Murio
581 2 25.00 female Sobrevive
582 1 39.00 female Sobrevive
605 1 35.00 male Sobrevive
606 3 36.00 male Murio
609 2 22.00 female Sobrevive
610 1 40.00 female Sobrevive
627 2 57.00 male Murio
632 3 51.00 male Murio
636 2 28.00 female Sobrevive
655 3 18.00 female Murio
667 2 25.00 male Murio
674 2 31.00 male Sobrevive
682 1 27.00 male Sobrevive
701 1 18.00 female Sobrevive
708 1 42.00 male Sobrevive
716 3 19.00 male Murio
734 2 23.00 male Murio
735 2 23.00 male Murio
742 1 36.00 male Murio
746 1 70.00 male Murio
752 3 6.00 male Sobrevive
760 1 33.00 female Sobrevive
763 3 20.00 male Sobrevive
768 3 30.50 female Murio
770 3 32.00 male Murio
773 2 57.00 female Murio
775 2 54.00 female Sobrevive
776 3 18.00 male Murio
778 3 5.00 female Sobrevive
785 3 25.00 male Murio
796 2 39.00 male Murio
797 1 49.00 female Sobrevive
817 3 23.00 female Murio
820 3 10.00 male Murio
831 3 15.00 female Sobrevive
834 3 23.00 male Murio
842 2 16.00 male Murio
846 3 42.00 male Murio
851 3 4.00 male Murio
858 1 51.00 male Sobrevive
866 2 42.00 female Sobrevive
871 3 26.00 male Murio
876 3 15.00 female Sobrevive
880 1 56.00 female Sobrevive
883 3 22.00 female Murio
891 3 32.00 male Murio