ACTIVIDAD 122: ANÁLISIS DE VARIABLES CUALITATIVAS Y CUANTITATIVAS

Análisis descriptivo de la base de datos de cervezas

Tu nombre aquí

09 de agosto de 2026

1. INTRODUCCIÓN

Este informe analiza dos variables cualitativas (tipo y nacionalidad) y dos variables cuantitativas (precio y calorías) de la base de datos de cervezas beer2.csv, usada también en la Actividad 121. Para las variables cualitativas se construye una tabla de frecuencia y se identifica la moda. Para las variables cuantitativas se construye una tabla de distribución de frecuencias por intervalos y se calculan los indicadores estadísticos correspondientes.

2. CARGA Y EXPLORACIÓN DE LOS DATOS

library(data.table)

cerveza <- fread("beer2.csv")

dim(cerveza)
## [1] 1586614      15
str(cerveza)
## Classes 'data.table' and 'data.frame':   1586614 obs. of  15 variables:
##  $ id            : int  47986 48213 48215 47969 64883 52159 52159 52159 52159 52159 ...
##  $ marca         : chr  "Vecchio Birraio" "Vecchio Birraio" "Vecchio Birraio" "Vecchio Birraio" ...
##  $ precio        : num  4.99 4.45 4.95 5.58 3.9 5.07 5.07 5.07 5.07 5.07 ...
##  $ alcohol       : num  13.8 16.9 17.7 13.8 20.7 ...
##  $ carbohidratos : num  11.5 14.2 15 10.5 15.2 12.1 12.1 12.1 12.1 12.1 ...
##  $ calorias      : int  148 181 190 144 212 145 145 145 145 145 ...
##  $ nacionalidad  : chr  "Canadá" "Canadá" "Canadá" "Canadá" ...
##  $ calificacion  : num  1.5 3 3 3 4 3 3.5 3 4 4.5 ...
##  $ aroma         : num  2 2.5 2.5 3 4.5 3.5 3.5 2.5 3 3.5 ...
##  $ apariencia    : num  2.5 3 3 3.5 4 3.5 3.5 3.5 3.5 5 ...
##  $ paladar       : num  1.5 3 3 2.5 4 3 4 2 3.5 4 ...
##  $ sabor         : num  1.5 3 3 3 4.5 3.5 4 3.5 4 4 ...
##  $ nombre_cerveza: chr  "Sausa Weizen" "Red Moon" "Black Horse Black Beer" "Sausa Pils" ...
##  $ tipo          : chr  "clara artesanal" "cerveza normal y helada" "cerveza normal y helada" "lager importada" ...
##  $ origen        : chr  "importada" "importada" "importada" "importada" ...
##  - attr(*, ".internal.selfref")=<pointer: 0x000001550e14eb00>

La base tiene 1.586.614 registros. Las variables elegidas para este análisis son tipo y nacionalidad (cualitativas), y precio y calorías (cuantitativas).

3. ANÁLISIS DE VARIABLES CUALITATIVAS

3.1 TIPO DE CERVEZA

tabla_tipo <- as.data.frame(table(cerveza$tipo))
names(tabla_tipo) <- c("tipo", "ni")
tabla_tipo <- tabla_tipo[order(-tabla_tipo$ni), ]

tabla_tipo$hi <- tabla_tipo$ni / nrow(cerveza)
tabla_tipo$Ni <- cumsum(tabla_tipo$ni)
tabla_tipo$Hi <- cumsum(tabla_tipo$hi)

knitr::kable(tabla_tipo, digits = 4, row.names = FALSE,
             caption = "Tabla de frecuencia - tipo de cerveza")
Tabla de frecuencia - tipo de cerveza
tipo ni hi Ni Hi
cerveza normal y helada 839088 0.5289 839088 0.5289
clara artesanal 483464 0.3047 1322552 0.8336
lager importada 219194 0.1382 1541746 0.9717
lager artesanal 22725 0.0143 1564471 0.9860
baja en calorías / sin alcohol 22143 0.0140 1586614 1.0000
moda_tipo <- tabla_tipo$tipo[which.max(tabla_tipo$ni)]
moda_tipo
## [1] cerveza normal y helada
## 5 Levels: baja en calorías / sin alcohol ... lager importada

INTERPRETACIÓN

El tipo más común es “cerveza normal y helada”, con 839.088 registros, el 52.89% del total. Le sigue “clara artesanal” con el 30.47%. Entre estos dos tipos suman más del 83% de toda la base. Los tipos “lager artesanal” y “baja en calorías / sin alcohol” son los menos comunes, cada uno con menos del 1.5% de los datos. Esto muestra que la base está compuesta en su mayoría por cervezas de tipo normal, y que las variedades artesanales bajas en calorías son poco frecuentes.

3.2 NACIONALIDAD

tabla_nac <- as.data.frame(table(cerveza$nacionalidad))
names(tabla_nac) <- c("nacionalidad", "ni")
tabla_nac <- tabla_nac[order(-tabla_nac$ni), ]

tabla_nac$hi <- tabla_nac$ni / nrow(cerveza)
tabla_nac$Ni <- cumsum(tabla_nac$ni)
tabla_nac$Hi <- cumsum(tabla_nac$hi)

knitr::kable(tabla_nac, digits = 4, row.names = FALSE,
             caption = "Tabla de frecuencia - nacionalidad")
Tabla de frecuencia - nacionalidad
nacionalidad ni hi Ni Hi
Austria 201941 0.1273 201941 0.1273
Bélgica 188677 0.1189 390618 0.2462
Francia 181574 0.1144 572192 0.3606
Estados Unidos 174165 0.1098 746357 0.4704
Inglaterra 162644 0.1025 909001 0.5729
Canadá 159508 0.1005 1068509 0.6735
Japón 155273 0.0979 1223782 0.7713
Alemania 121684 0.0767 1345466 0.8480
Irlanda 120742 0.0761 1466208 0.9241
República Checa 120406 0.0759 1586614 1.0000
moda_nac <- tabla_nac$nacionalidad[which.max(tabla_nac$ni)]
moda_nac
## [1] Austria
## 10 Levels: Alemania Austria Bélgica Canadá Estados Unidos ... República Checa

INTERPRETACIÓN

La nacionalidad con más registros es Austria, con el 12.73% del total, seguida de cerca por Bélgica (11.89%) y Francia (11.44%). La nacionalidad con menos registros es República Checa, con el 7.59%. A diferencia de la variable tipo, aquí no hay una categoría que domine claramente sobre las demás: las 10 nacionalidades tienen porcentajes bastante parecidos, todos entre el 7% y el 13%, lo que muestra que la base reúne cervezas de muchos países de forma bastante equilibrada.

4. ANÁLISIS DE VARIABLES CUANTITATIVAS

calcular_indicadores <- function(x) {
  n        <- length(x)
  minimo   <- min(x)
  maximo   <- max(x)
  media    <- mean(x)
  mediana  <- median(x)
  q1       <- as.numeric(quantile(x, 0.25))
  q3       <- as.numeric(quantile(x, 0.75))
  rango    <- maximo - minimo
  varianza <- var(x)
  desv_est <- sd(x)
  cv       <- (desv_est / media) * 100
  asimetria <- (sum((x - media)^3) / n) / (desv_est^3)
  curtosis <- (sum((x - media)^4) / n) / (desv_est^4) - 3

  data.frame(
    n = n, minimo = minimo, maximo = maximo, media = media,
    mediana = mediana, Q1 = q1, Q3 = q3, rango = rango,
    varianza = varianza, desviacion = desv_est, CV_pct = cv,
    asimetria = asimetria, curtosis = curtosis
  )
}

construir_tabla_frecuencia <- function(x) {
  n <- length(x)
  k <- ceiling(1 + 3.322 * log10(n))
  rango <- max(x) - min(x)
  amplitud <- rango / k

  limites <- seq(min(x), max(x), by = amplitud)
  limites[length(limites)] <- max(x) + 1e-9

  intervalos <- cut(x, breaks = limites, right = FALSE, include.lowest = TRUE)
  tabla <- as.data.frame(table(intervalos))
  names(tabla) <- c("intervalo", "ni")

  tabla$Li <- limites[-length(limites)]
  tabla$Ls <- limites[-1]
  tabla$xi <- (tabla$Li + tabla$Ls) / 2
  tabla$hi <- tabla$ni / n
  tabla$Ni <- cumsum(tabla$ni)
  tabla$Hi <- cumsum(tabla$hi)

  tabla
}

4.1 PRECIO

indicadores_precio <- calcular_indicadores(cerveza$precio)
knitr::kable(indicadores_precio, digits = 3,
             caption = "Indicadores estadísticos - precio")
Indicadores estadísticos - precio
n minimo maximo media mediana Q1 Q3 rango varianza desviacion CV_pct asimetria curtosis
1586614 2.37 7.72 5 5 4.36 5.64 5.35 0.784 0.885 17.708 0 -0.5
tabla_precio <- construir_tabla_frecuencia(cerveza$precio)
knitr::kable(tabla_precio[, c("intervalo", "Li", "Ls", "xi", "ni", "hi", "Ni", "Hi")],
             digits = 4, caption = "Tabla de distribución de frecuencias - precio")
Tabla de distribución de frecuencias - precio
intervalo Li Ls xi ni hi Ni Hi
[2.37,2.61) 2.3700 2.6132 2.4916 674 0.0004 674 0.0004
[2.61,2.86) 2.6132 2.8564 2.7348 4067 0.0026 4741 0.0030
[2.86,3.1) 2.8564 3.0995 2.9780 12118 0.0076 16859 0.0106
[3.1,3.34) 3.0995 3.3427 3.2211 27506 0.0173 44365 0.0280
[3.34,3.59) 3.3427 3.5859 3.4643 45047 0.0284 89412 0.0564
[3.59,3.83) 3.5859 3.8291 3.7075 68328 0.0431 157740 0.0994
[3.83,4.07) 3.8291 4.0723 3.9507 97011 0.0611 254751 0.1606
[4.07,4.32) 4.0723 4.3155 4.1939 116909 0.0737 371660 0.2342
[4.32,4.56) 4.3155 4.5586 4.4370 136622 0.0861 508282 0.3204
[4.56,4.8) 4.5586 4.8018 4.6802 156811 0.0988 665093 0.4192
[4.8,5.04) 4.8018 5.0450 4.9234 157873 0.0995 822966 0.5187
[5.04,5.29) 5.0450 5.2882 5.1666 155878 0.0982 978844 0.6169
[5.29,5.53) 5.2882 5.5314 5.4098 152753 0.0963 1131597 0.7132
[5.53,5.77) 5.5314 5.7745 5.6530 130084 0.0820 1261681 0.7952
[5.77,6.02) 5.7745 6.0177 5.8961 108164 0.0682 1369845 0.8634
[6.02,6.26) 6.0177 6.2609 6.1393 87416 0.0551 1457261 0.9185
[6.26,6.5) 6.2609 6.5041 6.3825 59394 0.0374 1516655 0.9559
[6.5,6.75) 6.5041 6.7473 6.6257 37819 0.0238 1554474 0.9797
[6.75,6.99) 6.7473 6.9905 6.8689 21128 0.0133 1575602 0.9931
[6.99,7.23) 6.9905 7.2336 7.1120 8446 0.0053 1584048 0.9984
[7.23,7.48) 7.2336 7.4768 7.3552 2327 0.0015 1586375 0.9998
[7.48,7.72] 7.4768 7.7200 7.5984 239 0.0002 1586614 1.0000
intervalo_modal_precio <- tabla_precio[which.max(tabla_precio$ni), ]
intervalo_modal_precio
##     intervalo     ni       Li    Ls       xi         hi     Ni        Hi
## 11 [4.8,5.04) 157873 4.801818 5.045 4.923409 0.09950309 822966 0.5186933
hist(cerveza$precio, breaks = c(tabla_precio$Li, tail(tabla_precio$Ls, 1)),
     col = "steelblue", border = "white",
     main = "Distribución del precio", xlab = "precio", ylab = "Frecuencia absoluta")
abline(v = indicadores_precio$media, col = "red", lwd = 2, lty = 2)
legend("topright", legend = "Media", col = "red", lty = 2, lwd = 2)

INTERPRETACIÓN

El precio tiene una media de 5.00 y una mediana de 5.00, casi iguales, y una asimetría muy cerca de cero (-0.0005), lo que muestra que los datos están repartidos de forma pareja a los dos lados de la media. La curtosis negativa (-0.50) indica que la distribución es plana, sin un punto donde se junten muchos datos. El intervalo con más cervezas es el que va de 4.80 a 5.05, con cerca del 9.95% del total. El precio varía entre 2.37 y 7.72, con una variabilidad moderada (CV = 17.71%).

4.2 CALORÍAS

indicadores_calorias <- calcular_indicadores(cerveza$calorias)
knitr::kable(indicadores_calorias, digits = 3,
             caption = "Indicadores estadísticos - calorías")
Indicadores estadísticos - calorías
n minimo maximo media mediana Q1 Q3 rango varianza desviacion CV_pct asimetria curtosis
1586614 21 541 193.173 182 157 224 520 2168.646 46.569 24.107 0.915 1.318
tabla_calorias <- construir_tabla_frecuencia(cerveza$calorias)
knitr::kable(tabla_calorias[, c("intervalo", "Li", "Ls", "xi", "ni", "hi", "Ni", "Hi")],
             digits = 4, caption = "Tabla de distribución de frecuencias - calorías")
Tabla de distribución de frecuencias - calorías
intervalo Li Ls xi ni hi Ni Hi
[21,44.6) 21.0000 44.6364 32.8182 1208 0.0008 1208 0.0008
[44.6,68.3) 44.6364 68.2727 56.4545 184 0.0001 1392 0.0009
[68.3,91.9) 68.2727 91.9091 80.0909 2217 0.0014 3609 0.0023
[91.9,116) 91.9091 115.5455 103.7273 7296 0.0046 10905 0.0069
[116,139) 115.5455 139.1818 127.3636 82993 0.0523 93898 0.0592
[139,163) 139.1818 162.8182 151.0000 419367 0.2643 513265 0.3235
[163,186) 162.8182 186.4545 174.6364 318845 0.2010 832110 0.5245
[186,210) 186.4545 210.0909 198.2727 245145 0.1545 1077255 0.6790
[210,234) 210.0909 233.7273 221.9091 181565 0.1144 1258820 0.7934
[234,257) 233.7273 257.3636 245.5455 168412 0.1061 1427232 0.8995
[257,281) 257.3636 281.0000 269.1818 97610 0.0615 1524842 0.9611
[281,305) 281.0000 304.6364 292.8182 35721 0.0225 1560563 0.9836
[305,328) 304.6364 328.2727 316.4545 9419 0.0059 1569982 0.9895
[328,352) 328.2727 351.9091 340.0909 7307 0.0046 1577289 0.9941
[352,376) 351.9091 375.5455 363.7273 2465 0.0016 1579754 0.9957
[376,399) 375.5455 399.1818 387.3636 6089 0.0038 1585843 0.9995
[399,423) 399.1818 422.8182 411.0000 49 0.0000 1585892 0.9995
[423,446) 422.8182 446.4545 434.6364 65 0.0000 1585957 0.9996
[446,470) 446.4545 470.0909 458.2727 460 0.0003 1586417 0.9999
[470,494) 470.0909 493.7273 481.9091 108 0.0001 1586525 0.9999
[494,517) 493.7273 517.3636 505.5455 10 0.0000 1586535 1.0000
[517,541] 517.3636 541.0000 529.1818 79 0.0000 1586614 1.0000
intervalo_modal_calorias <- tabla_calorias[which.max(tabla_calorias$ni), ]
intervalo_modal_calorias
##   intervalo     ni       Li       Ls  xi        hi     Ni        Hi
## 6 [139,163) 419367 139.1818 162.8182 151 0.2643157 513265 0.3234971
hist(cerveza$calorias, breaks = c(tabla_calorias$Li, tail(tabla_calorias$Ls, 1)),
     col = "darkorange", border = "white",
     main = "Distribución de las calorías", xlab = "calorías", ylab = "Frecuencia absoluta")
abline(v = indicadores_calorias$media, col = "red", lwd = 2, lty = 2)
legend("topright", legend = "Media", col = "red", lty = 2, lwd = 2)

INTERPRETACIÓN

Las calorías tienen una media de 193.17 y una mediana de 182, un poco más baja que la media, lo que ya avisa que hay valores altos que suben el promedio. Esto se confirma con la asimetría positiva (0.92): la mayoría de las cervezas tienen pocas calorías, pero hay un grupo con muchas más calorías que estira la distribución hacia la derecha. La curtosis positiva (1.32) muestra que los datos están bastante juntos alrededor de la media. El intervalo con más cervezas es el que va de 139.18 a 162.82 calorías, con cerca del 26.43% del total, casi la cuarta parte de toda la base. Las calorías van de 21 a 541, con una variabilidad más alta que la del precio (CV = 24.11%).

5. CONCLUSIONES

En cuanto a las variables cualitativas, el tipo de cerveza muestra una categoría muy dominante (“cerveza normal y helada”, más de la mitad de la base), mientras que la nacionalidad está mucho más repartida entre los 10 países, sin que ninguno se destaque demasiado sobre los demás. En cuanto a las variables cuantitativas, el precio es una variable pareja y sin inclinarse hacia ningún lado, con una variabilidad moderada, mientras que las calorías se inclinan hacia valores altos y tienen más variabilidad, señal de que existe un grupo de cervezas mucho más calóricas que el resto. En conjunto, el análisis muestra una base de datos con categorías bien definidas en cuanto a tipo, un buen equilibrio entre nacionalidades, y dos variables numéricas con comportamientos distintos: una más estable (precio) y otra con más variación y cervezas que se alejan del promedio (calorías).