1 Introducción

Este informe tiene como objetivo hacer un primer diagnóstico descriptivo sobre una base de datos de reseñas de cerveza, a petición de una empresa del sector cervecero que busca entender mejor las preferencias de los consumidores.

La base de datos beer2.csv contiene 1.586.614 reseñas y 15 variables que cubren desde información del producto (tipo, marca, origen, composición nutricional) hasta valoraciones sensoriales dadas por los consumidores (aroma, sabor, apariencia, paladar y calificación general). Cada fila es una reseña, así que una misma cerveza puede aparecer muchas veces si tiene varias reseñas.

Es importante aclarar que la variable precio fue simulada, por lo que los resultados sobre precios aplican solo dentro de esta base y no se deben tomar como datos reales del mercado. Además, al tratarse de un análisis descriptivo, lo que podemos hacer es identificar patrones y diferencias, pero no podemos afirmar que una variable cause cambios en otra.

2 Carga de datos y librerías

library(tidyverse)
library(knitr)
library(kableExtra)
library(scales)
beer <- read_csv("beer2.csv")

Verificamos que todo se haya cargado correctamente:

dim(beer)
## [1] 1586614      15
sum(is.na(beer))
## [1] 0

Son 1,586,614 filas y 15 columnas, sin datos faltantes. Ahora vemos las primeras filas para familiarizarnos con la estructura:

head(beer, 8) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE, font_size = 12) %>%
  scroll_box(width = "100%")
id marca precio alcohol carbohidratos calorias nacionalidad calificacion aroma apariencia paladar sabor nombre_cerveza tipo origen
47986 Vecchio Birraio 4.99 13.75 11.5 148 Canadá 1.5 2.0 2.5 1.5 1.5 Sausa Weizen clara artesanal importada
48213 Vecchio Birraio 4.45 16.90 14.2 181 Canadá 3.0 2.5 3.0 3.0 3.0 Red Moon cerveza normal y helada importada
48215 Vecchio Birraio 4.95 17.67 15.0 190 Canadá 3.0 2.5 3.0 3.0 3.0 Black Horse Black Beer cerveza normal y helada importada
47969 Vecchio Birraio 5.58 13.75 10.5 144 Canadá 3.0 3.0 3.5 2.5 3.0 Sausa Pils lager importada importada
64883 Caldera Brewing Company 3.90 20.69 15.2 212 Canadá 4.0 4.5 4.0 4.0 4.5 Cauldron DIPA clara artesanal importada
52159 Caldera Brewing Company 5.07 12.95 12.1 145 Canadá 3.0 3.5 3.5 3.0 3.5 Caldera Ginger Beer cerveza normal y helada importada
52159 Caldera Brewing Company 5.07 12.95 12.1 145 Canadá 3.5 3.5 3.5 4.0 4.0 Caldera Ginger Beer cerveza normal y helada importada
52159 Caldera Brewing Company 5.07 12.95 12.1 145 Canadá 3.0 2.5 3.5 2.0 3.5 Caldera Ginger Beer cerveza normal y helada importada
glimpse(beer)
## Rows: 1,586,614
## Columns: 15
## $ id             <dbl> 47986, 48213, 48215, 47969, 64883, 52159, 52159, 52159,…
## $ marca          <chr> "Vecchio Birraio", "Vecchio Birraio", "Vecchio Birraio"…
## $ precio         <dbl> 4.99, 4.45, 4.95, 5.58, 3.90, 5.07, 5.07, 5.07, 5.07, 5…
## $ alcohol        <dbl> 13.75, 16.90, 17.67, 13.75, 20.69, 12.95, 12.95, 12.95,…
## $ carbohidratos  <dbl> 11.5, 14.2, 15.0, 10.5, 15.2, 12.1, 12.1, 12.1, 12.1, 1…
## $ calorias       <dbl> 148, 181, 190, 144, 212, 145, 145, 145, 145, 145, 112, …
## $ nacionalidad   <chr> "Canadá", "Canadá", "Canadá", "Canadá", "Canadá", "Cana…
## $ calificacion   <dbl> 1.5, 3.0, 3.0, 3.0, 4.0, 3.0, 3.5, 3.0, 4.0, 4.5, 3.0, …
## $ aroma          <dbl> 2.0, 2.5, 2.5, 3.0, 4.5, 3.5, 3.5, 2.5, 3.0, 3.5, 2.0, …
## $ apariencia     <dbl> 2.5, 3.0, 3.0, 3.5, 4.0, 3.5, 3.5, 3.5, 3.5, 5.0, 3.0, …
## $ paladar        <dbl> 1.5, 3.0, 3.0, 2.5, 4.0, 3.0, 4.0, 2.0, 3.5, 4.0, 2.5, …
## $ sabor          <dbl> 1.5, 3.0, 3.0, 3.0, 4.5, 3.5, 4.0, 3.5, 4.0, 4.0, 2.5, …
## $ nombre_cerveza <chr> "Sausa Weizen", "Red Moon", "Black Horse Black Beer", "…
## $ tipo           <chr> "clara artesanal", "cerveza normal y helada", "cerveza …
## $ origen         <chr> "importada", "importada", "importada", "importada", "im…

2.1 Clasificación de las variables

Según el enunciado, las variables se clasifican de la siguiente forma:

data.frame(
  Variable = c("id", "marca", "precio", "alcohol", "carbohidratos", "calorias",
               "nacionalidad", "calificacion", "aroma", "apariencia", "paladar",
               "sabor", "nombre_cerveza", "tipo", "origen"),
  Tipo = c("Identificador (Cualitativa nominal)",
           "Cualitativa nominal",
           "Cuantitativa de razón",
           "Cuantitativa de razón",
           "Cuantitativa de razón",
           "Cuantitativa de razón",
           "Cualitativa nominal",
           "Cualitativa ordinal",
           "Cualitativa ordinal",
           "Cualitativa ordinal",
           "Cualitativa ordinal",
           "Cualitativa ordinal",
           "Cualitativa nominal",
           "Cualitativa nominal",
           "Cualitativa nominal")
) %>%
  kable() %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Variable Tipo
id Identificador (Cualitativa nominal)
marca Cualitativa nominal
precio Cuantitativa de razón
alcohol Cuantitativa de razón
carbohidratos Cuantitativa de razón
calorias Cuantitativa de razón
nacionalidad Cualitativa nominal
calificacion Cualitativa ordinal
aroma Cualitativa ordinal
apariencia Cualitativa ordinal
paladar Cualitativa ordinal
sabor Cualitativa ordinal
nombre_cerveza Cualitativa nominal
tipo Cualitativa nominal
origen Cualitativa nominal

3 Análisis de variables cualitativas

Para cada variable cualitativa se construyen tablas de frecuencias absolutas y relativas, y se identifica la moda.

3.1 Tipo de cerveza

tabla_tipo <- beer %>%
  count(tipo) %>%
  arrange(desc(n)) %>%
  mutate(frecuencia_relativa = n / sum(n),
         porcentaje = round(frecuencia_relativa * 100, 2))

tabla_tipo %>%
  kable(col.names = c("Tipo", "Frecuencia absoluta", "Frecuencia relativa", "Porcentaje (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Tipo Frecuencia absoluta Frecuencia relativa Porcentaje (%)
cerveza normal y helada 839088 0.5288545 52.89
clara artesanal 483464 0.3047143 30.47
lager importada 219194 0.1381521 13.82
lager artesanal 22725 0.0143230 1.43
baja en calorías / sin alcohol 22143 0.0139561 1.40

La moda es cerveza normal y helada con 839,088 reseñas.

ggplot(tabla_tipo, aes(x = reorder(tipo, n), y = n)) +
  geom_col(fill = "steelblue") +
  coord_flip() +
  scale_y_continuous(labels = comma) +
  labs(x = NULL, y = "Cantidad de reseñas", title = "Reseñas por tipo de cerveza") +
  theme_minimal()

3.2 Origen

tabla_origen <- beer %>%
  count(origen) %>%
  arrange(desc(n)) %>%
  mutate(frecuencia_relativa = n / sum(n),
         porcentaje = round(frecuencia_relativa * 100, 2))

tabla_origen %>%
  kable(col.names = c("Origen", "Frecuencia absoluta", "Frecuencia relativa", "Porcentaje (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Origen Frecuencia absoluta Frecuencia relativa Porcentaje (%)
importada 1412449 0.8902285 89.02
nacional 174165 0.1097715 10.98

La moda es importada.

ggplot(tabla_origen, aes(x = reorder(origen, n), y = n)) +
  geom_col(fill = "darkgreen", width = 0.5) +
  coord_flip() +
  scale_y_continuous(labels = comma) +
  labs(x = NULL, y = "Cantidad de reseñas", title = "Reseñas por origen") +
  theme_minimal()

3.3 Nacionalidad

Como hay muchas nacionalidades, mostramos las 15 con más reseñas:

tabla_nac <- beer %>%
  count(nacionalidad) %>%
  arrange(desc(n)) %>%
  mutate(frecuencia_relativa = n / sum(n),
         porcentaje = round(frecuencia_relativa * 100, 2))

tabla_nac %>%
  head(15) %>%
  kable(col.names = c("Nacionalidad", "Frec. absoluta", "Frec. relativa", "Porcentaje (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Nacionalidad Frec. absoluta Frec. relativa Porcentaje (%)
Austria 201941 0.1272780 12.73
Bélgica 188677 0.1189180 11.89
Francia 181574 0.1144412 11.44
Estados Unidos 174165 0.1097715 10.98
Inglaterra 162644 0.1025101 10.25
Canadá 159508 0.1005336 10.05
Japón 155273 0.0978644 9.79
Alemania 121684 0.0766941 7.67
Irlanda 120742 0.0761004 7.61
República Checa 120406 0.0758887 7.59

La moda es Austria.

tabla_nac %>%
  head(10) %>%
  ggplot(aes(x = reorder(nacionalidad, n), y = n)) +
  geom_col(fill = "mediumpurple") +
  coord_flip() +
  scale_y_continuous(labels = comma) +
  labs(x = NULL, y = "Cantidad de reseñas", title = "Top 10 nacionalidades") +
  theme_minimal()

4 Análisis de variables ordinales

Las variables de valoración (calificación, aroma, apariencia, paladar y sabor) son ordinales. Construimos la tabla de frecuencias de cada una para ver cómo se distribuyen las puntuaciones.

4.1 Calificación general

tabla_calif <- beer %>%
  count(calificacion) %>%
  mutate(frecuencia_relativa = n / sum(n),
         porcentaje = round(frecuencia_relativa * 100, 2))

tabla_calif %>%
  kable(col.names = c("Calificación", "Frec. absoluta", "Frec. relativa", "%")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Calificación Frec. absoluta Frec. relativa %
0.0 7 0.0000044 0.00
1.0 10954 0.0069040 0.69
1.5 12975 0.0081778 0.82
2.0 38225 0.0240922 2.41
2.5 58523 0.0368855 3.69
3.0 165644 0.1044009 10.44
3.5 301817 0.1902271 19.02
4.0 582764 0.3673004 36.73
4.5 324385 0.2044511 20.45
5.0 91320 0.0575565 5.76

La moda de calificación es 4 para las variables ordinales en general.

4.2 Aroma

tabla_aroma <- beer %>%
  count(aroma) %>%
  mutate(frecuencia_relativa = n / sum(n),
         porcentaje = round(frecuencia_relativa * 100, 2))

tabla_aroma %>%
  kable(col.names = c("Aroma", "Frec. absoluta", "Frec. relativa", "%")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Aroma Frec. absoluta Frec. relativa %
1.0 6873 0.0043319 0.43
1.5 12524 0.0078935 0.79
2.0 42566 0.0268282 2.68
2.5 66359 0.0418243 4.18
3.0 200030 0.1260735 12.61
3.5 365312 0.2302463 23.02
4.0 557383 0.3513035 35.13
4.5 271450 0.1710876 17.11
5.0 64117 0.0404112 4.04

La moda de aroma es 4.

4.3 Apariencia

tabla_apariencia <- beer %>%
  count(apariencia) %>%
  mutate(frecuencia_relativa = n / sum(n),
         porcentaje = round(frecuencia_relativa * 100, 2))

tabla_apariencia %>%
  kable(col.names = c("Apariencia", "Frec. absoluta", "Frec. relativa", "%")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Apariencia Frec. absoluta Frec. relativa %
0.0 7 0.0000044 0.00
1.0 3323 0.0020944 0.21
1.5 6147 0.0038743 0.39
2.0 25414 0.0160178 1.60
2.5 39493 0.0248914 2.49
3.0 166009 0.1046310 10.46
3.5 318529 0.2007602 20.08
4.0 674186 0.4249212 42.49
4.5 288108 0.1815867 18.16
5.0 65398 0.0412186 4.12

La moda de apariencia es 4.

4.4 Paladar

tabla_paladar <- beer %>%
  count(paladar) %>%
  mutate(frecuencia_relativa = n / sum(n),
         porcentaje = round(frecuencia_relativa * 100, 2))

tabla_paladar %>%
  kable(col.names = c("Paladar", "Frec. absoluta", "Frec. relativa", "%")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Paladar Frec. absoluta Frec. relativa %
1.0 6874 0.0043325 0.43
1.5 11045 0.0069614 0.70
2.0 38333 0.0241603 2.42
2.5 62842 0.0396076 3.96
3.0 206932 0.1304237 13.04
3.5 338585 0.2134010 21.34
4.0 606711 0.3823936 38.24
4.5 253102 0.1595234 15.95
5.0 62190 0.0391967 3.92

La moda de paladar es 4.

4.5 Sabor

tabla_sabor <- beer %>%
  count(sabor) %>%
  mutate(frecuencia_relativa = n / sum(n),
         porcentaje = round(frecuencia_relativa * 100, 2))

tabla_sabor %>%
  kable(col.names = c("Sabor", "Frec. absoluta", "Frec. relativa", "%")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Sabor Frec. absoluta Frec. relativa %
1.0 9991 0.0062971 0.63
1.5 15128 0.0095348 0.95
2.0 41992 0.0264664 2.65
2.5 66534 0.0419346 4.19
3.0 166860 0.1051674 10.52
3.5 324541 0.2045494 20.45
4.0 541429 0.3412481 34.12
4.5 336162 0.2118738 21.19
5.0 83977 0.0529284 5.29

La moda de sabor es 4.

4.6 Visualización conjunta de las valoraciones

Para tener un panorama general de las cinco variables ordinales juntas:

beer %>%
  select(calificacion, aroma, apariencia, paladar, sabor) %>%
  pivot_longer(everything(), names_to = "variable", values_to = "valor") %>%
  count(variable, valor) %>%
  ggplot(aes(x = factor(valor), y = n)) +
  geom_col(fill = "coral") +
  facet_wrap(~ variable, scales = "free_y", ncol = 2) +
  scale_y_continuous(labels = comma) +
  labs(x = "Puntuación", y = "Frecuencia",
       title = "Distribución de las valoraciones sensoriales") +
  theme_minimal()

5 Análisis de variables cuantitativas

Para las variables cuantitativas (precio, alcohol, carbohidratos y calorías) calculamos indicadores de tendencia central, posición y dispersión.

5.1 Tabla resumen

# Armamos la tabla manualmente para cada variable
resumen <- data.frame(
  Variable = c("precio", "alcohol", "carbohidratos", "calorias"),
  Media = c(round(mean(beer$precio), 2),
            round(mean(beer$alcohol), 2),
            round(mean(beer$carbohidratos), 2),
            round(mean(beer$calorias), 2)),
  Mediana = c(round(median(beer$precio), 2),
              round(median(beer$alcohol), 2),
              round(median(beer$carbohidratos), 2),
              round(median(beer$calorias), 2)),
  Desv_Est = c(round(sd(beer$precio), 2),
               round(sd(beer$alcohol), 2),
               round(sd(beer$carbohidratos), 2),
               round(sd(beer$calorias), 2)),
  Min = c(round(min(beer$precio), 2),
          round(min(beer$alcohol), 2),
          round(min(beer$carbohidratos), 2),
          round(min(beer$calorias), 2)),
  Q1 = c(round(quantile(beer$precio, 0.25), 2),
         round(quantile(beer$alcohol, 0.25), 2),
         round(quantile(beer$carbohidratos, 0.25), 2),
         round(quantile(beer$calorias, 0.25), 2)),
  Q3 = c(round(quantile(beer$precio, 0.75), 2),
         round(quantile(beer$alcohol, 0.75), 2),
         round(quantile(beer$carbohidratos, 0.75), 2),
         round(quantile(beer$calorias, 0.75), 2)),
  Max = c(round(max(beer$precio), 2),
          round(max(beer$alcohol), 2),
          round(max(beer$carbohidratos), 2),
          round(max(beer$calorias), 2)),
  RIQ = c(round(IQR(beer$precio), 2),
          round(IQR(beer$alcohol), 2),
          round(IQR(beer$carbohidratos), 2),
          round(IQR(beer$calorias), 2)),
  CV = c(round(sd(beer$precio)/mean(beer$precio)*100, 2),
         round(sd(beer$alcohol)/mean(beer$alcohol)*100, 2),
         round(sd(beer$carbohidratos)/mean(beer$carbohidratos)*100, 2),
         round(sd(beer$calorias)/mean(beer$calorias)*100, 2))
)

resumen %>%
  kable(col.names = c("Variable", "Media", "Mediana", "Desv. Est.", "Mín.",
                      "Q1", "Q3", "Máx.", "RIQ", "CV (%)")) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Variable Media Mediana Desv. Est. Mín. Q1 Q3 Máx. RIQ CV (%)
precio 5.00 5.00 0.89 2.37 4.36 5.64 7.72 1.28 17.71
alcohol 18.71 17.67 5.46 0.03 14.28 22.63 59.45 8.35 29.16
carbohidratos 14.05 13.80 2.38 3.50 12.40 15.60 30.20 3.20 16.91
calorias 193.17 182.00 46.57 21.00 157.00 224.00 541.00 67.00 24.11

El Coeficiente de Variación (CV) nos ayuda a saber qué tan dispersos están los datos respecto a la media. Si el CV es bajo (menor a 15%), los datos son bastante homogéneos; si es alto (mayor a 30%), hay mucha variabilidad y probablemente la mediana represente mejor a los datos que la media.

También es importante comparar la media con la mediana: si son muy parecidas, la distribución es simétrica; si la media es mayor que la mediana, hay asimetría hacia la derecha (valores altos que jalan la media) y si la media es menor que la mediana, hay asimetria hacia la izquierda (valores bajos que jalan la media).

5.2 Histogramas

beer %>%
  select(precio, alcohol, carbohidratos, calorias) %>%
  pivot_longer(everything(), names_to = "variable", values_to = "valor") %>%
  ggplot(aes(x = valor)) +
  geom_histogram(fill = "steelblue", color = "white", bins = 100) +
  facet_wrap(~ variable, scales = "free", ncol = 2) +
  scale_y_continuous(labels = comma) +
  labs(x = "Valor", y = "Frecuencia", title = "Histogramas de variables cuantitativas") +
  theme_minimal()

5.3 Diagramas de caja

beer %>%
  select(precio, alcohol, carbohidratos, calorias) %>%
  pivot_longer(everything(), names_to = "variable", values_to = "valor") %>%
  ggplot(aes(x = variable, y = valor)) +
  geom_boxplot(fill = "steelblue", color = "black", outlier.size = 0.3, outlier.alpha = 0.1) +
  facet_wrap(~ variable, scales = "free", ncol = 2) +
  labs(x = NULL, y = "Valor", title = "Boxplots de variables cuantitativas") +
  theme_minimal()

6 Comparaciones por tipo y origen

6.1 Variables cuantitativas por tipo de cerveza

beer %>%
  group_by(tipo) %>%
  summarise(
    n = n(),
    media_precio = round(mean(precio), 2),
    mediana_precio = round(median(precio), 2),
    de_precio = round(sd(precio), 2),
    media_alcohol = round(mean(alcohol), 2),
    mediana_alcohol = round(median(alcohol), 2),
    de_alcohol = round(sd(alcohol), 2),
    media_calorias = round(mean(calorias), 2),
    mediana_calorias = round(median(calorias), 2),
    de_calorias = round(sd(calorias), 2)
  ) %>%
  kable(caption = "Indicadores por tipo de cerveza") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = TRUE, font_size = 11) %>%
  scroll_box(width = "100%")
Indicadores por tipo de cerveza
tipo n media_precio mediana_precio de_precio media_alcohol mediana_alcohol de_alcohol media_calorias mediana_calorias de_calorias
baja en calorías / sin alcohol 22143 4.99 4.98 0.80 9.84 11.07 2.66 109.52 116 23.04
cerveza normal y helada 839088 4.99 4.99 0.89 20.10 18.94 5.77 203.82 198 49.05
clara artesanal 483464 5.00 4.99 0.89 18.15 17.41 4.58 191.10 184 39.24
lager artesanal 22725 5.07 5.03 0.80 15.67 13.75 3.78 169.88 158 32.87
lager importada 219194 5.03 5.05 0.89 15.86 14.28 3.84 167.84 156 32.83
beer %>%
  select(tipo, precio, alcohol, carbohidratos, calorias) %>%
  pivot_longer(-tipo, names_to = "variable", values_to = "valor") %>%
  ggplot(aes(x = tipo, y = valor, fill = tipo)) +
  geom_boxplot(outlier.size = 0.2, outlier.alpha = 0.1, show.legend = FALSE) +
  facet_wrap(~ variable, scales = "free_y", ncol = 2) +
  labs(x = NULL, y = "Valor", title = "Variables cuantitativas según tipo de cerveza") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 30, hjust = 1, size = 7))

6.2 Variables cuantitativas por origen

beer %>%
  group_by(origen) %>%
  summarise(
    n = n(),
    media_precio = round(mean(precio), 2),
    mediana_precio = round(median(precio), 2),
    de_precio = round(sd(precio), 2),
    media_alcohol = round(mean(alcohol), 2),
    mediana_alcohol = round(median(alcohol), 2),
    de_alcohol = round(sd(alcohol), 2),
    media_calorias = round(mean(calorias), 2),
    mediana_calorias = round(median(calorias), 2),
    de_calorias = round(sd(calorias), 2)
  ) %>%
  kable(caption = "Indicadores por origen") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Indicadores por origen
origen n media_precio mediana_precio de_precio media_alcohol mediana_alcohol de_alcohol media_calorias mediana_calorias de_calorias
importada 1412449 5.00 5.00 0.88 18.71 17.41 5.47 193.06 182 46.72
nacional 174165 5.02 5.03 0.90 18.73 17.93 5.35 194.06 188 45.31
beer %>%
  select(origen, precio, alcohol, carbohidratos, calorias) %>%
  pivot_longer(-origen, names_to = "variable", values_to = "valor") %>%
  ggplot(aes(x = origen, y = valor, fill = origen)) +
  geom_boxplot(outlier.size = 0.2, outlier.alpha = 0.1, show.legend = FALSE) +
  facet_wrap(~ variable, scales = "free_y", ncol = 2) +
  labs(x = NULL, y = "Valor", title = "Variables cuantitativas según origen") +
  theme_minimal()

6.3 Valoraciones por tipo de cerveza

beer %>%
  group_by(tipo) %>%
  summarise(
    mediana_calificacion = median(calificacion),
    media_calificacion = round(mean(calificacion), 2),
    mediana_aroma = median(aroma),
    media_aroma = round(mean(aroma), 2),
    mediana_sabor = median(sabor),
    media_sabor = round(mean(sabor), 2),
    mediana_paladar = median(paladar),
    media_paladar = round(mean(paladar), 2),
    mediana_apariencia = median(apariencia),
    media_apariencia = round(mean(apariencia), 2)
  ) %>%
  kable(caption = "Valoraciones por tipo de cerveza") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = TRUE, font_size = 11) %>%
  scroll_box(width = "100%")
Valoraciones por tipo de cerveza
tipo mediana_calificacion media_calificacion mediana_aroma media_aroma mediana_sabor media_sabor mediana_paladar media_paladar mediana_apariencia media_apariencia
baja en calorías / sin alcohol 3 2.95 2.5 2.58 2.5 2.64 2.5 2.68 3.0 2.82
cerveza normal y helada 4 3.86 4.0 3.85 4.0 3.90 4.0 3.83 4.0 3.94
clara artesanal 4 3.88 4.0 3.78 4.0 3.82 4.0 3.79 4.0 3.87
lager artesanal 4 3.64 3.5 3.37 3.5 3.49 3.5 3.49 3.5 3.59
lager importada 4 3.61 3.5 3.34 3.5 3.48 3.5 3.47 3.5 3.55
beer %>%
  select(tipo, calificacion, aroma, apariencia, paladar, sabor) %>%
  pivot_longer(-tipo, names_to = "atributo", values_to = "puntuacion") %>%
  ggplot(aes(x = tipo, y = puntuacion, fill = tipo)) +
  geom_boxplot(outlier.size = 0.2, outlier.alpha = 0.1, show.legend = FALSE) +
  facet_wrap(~ atributo, scales = "free_y", ncol = 2) +
  labs(x = NULL, y = "Puntuación", title = "Valoraciones sensoriales por tipo de cerveza") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 30, hjust = 1, size = 7))

6.4 Valoraciones por origen

beer %>%
  group_by(origen) %>%
  summarise(
    mediana_calificacion = median(calificacion),
    media_calificacion = round(mean(calificacion), 2),
    mediana_aroma = median(aroma),
    media_aroma = round(mean(aroma), 2),
    mediana_sabor = median(sabor),
    media_sabor = round(mean(sabor), 2),
    mediana_paladar = median(paladar),
    media_paladar = round(mean(paladar), 2),
    mediana_apariencia = median(apariencia),
    media_apariencia = round(mean(apariencia), 2)
  ) %>%
  kable(caption = "Valoraciones por origen") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Valoraciones por origen
origen mediana_calificacion media_calificacion mediana_aroma media_aroma mediana_sabor media_sabor mediana_paladar media_paladar mediana_apariencia media_apariencia
importada 4 3.81 4 3.73 4 3.79 4 3.74 4 3.84
nacional 4 3.85 4 3.77 4 3.82 4 3.77 4 3.88
beer %>%
  select(origen, calificacion, aroma, apariencia, paladar, sabor) %>%
  pivot_longer(-origen, names_to = "atributo", values_to = "puntuacion") %>%
  ggplot(aes(x = origen, y = puntuacion, fill = origen)) +
  geom_boxplot(outlier.size = 0.2, outlier.alpha = 0.1, show.legend = FALSE) +
  facet_wrap(~ atributo, scales = "free_y", ncol = 2) +
  labs(x = NULL, y = "Puntuación", title = "Valoraciones sensoriales por origen") +
  theme_minimal()

7 Conclusiones

A partir del análisis descriptivo realizado se pueden señalar los siguientes patrones generales:

  • La base de datos está compuesta en su gran mayoría por reseñas de un tipo de cerveza en particular, lo que significa que los promedios generales están fuertemente influenciados por esa categoría. Sería importante tener esto en cuenta si en el futuro se quieren hacer comparaciones más equilibradas.

  • Al observar las variables cuantitativas, se puede notar que alcohol, carbohidratos y calorías tienden a moverse juntas: las cervezas con más alcohol suelen tener también más carbohidratos y calorías, lo cual tiene sentido desde un punto de vista nutricional. Sin embargo, este informe no puede confirmar una relación causal entre ellas.

  • En las comparaciones por tipo de cerveza se observan diferencias en los indicadores. Por ejemplo, las cervezas artesanales tienden a presentar valores distintos de alcohol y calorías en comparación con las cervezas bajas en calorías o sin alcohol, lo cual es esperable dada la naturaleza de cada categoría.

  • Las valoraciones sensoriales (aroma, sabor, paladar, apariencia) muestran patrones similares entre sí: cuando una cerveza recibe buenas puntuaciones en un atributo, suele recibirlas también en los demás. Esto sugiere que la experiencia del consumidor tiende a ser consistente.

  • Sobre las diferencias por origen (nacional vs. importada), los datos permiten observar si hay alguna tendencia en las valoraciones y la composición, aunque las diferencias podrían deberse a la composición desigual de la base.

Consideraciones finales:

  • La variable precio es simulada, por lo que las observaciones sobre precios describen únicamente esta base académica y no el mercado real.
  • Al ser un análisis descriptivo, los patrones encontrados sirven para formular hipótesis que podrían investigarse con métodos estadísticos más avanzados, pero no se pueden establecer relaciones de causa y efecto.
  • Cada fila representa una reseña, no una cerveza única, por lo que las cervezas más reseñadas tienen más peso en los resultados generales.

Informe elaborado por Sergio Amaya — 2026-08-11