diamonds <- read.csv("/Users/angelicagonzalez/Downloads/diamonds.csv")
head(diamonds)
##   carat       cut color clarity depth table price    x    y    z
## 1  0,23     Ideal     E     SI2  61,5    55   326 3,95 3,98 2,43
## 2  0,21   Premium     E     SI1  59,8    61   326 3,89 3,84 2,31
## 3  0,23      Good     E     VS1  56,9    65   327 4,05 4,07 2,31
## 4  0,29   Premium     I     VS2  62,4    58   334 4,20 4,23 2,63
## 5  0,31      Good     J     SI2  63,3    58   335 4,34 4,35 2,75
## 6  0,24 Very Good     J    VVS2  62,8    57   336 3,94 3,96 2,48

1 Introducción

1.1 La base de datos elegida

Este informe analiza la base diamonds, una base de datos pública que viene incluida en el paquete ggplot2 de R y que es de las más usadas en el mundo para enseñar estadística descriptiva.

Nombre diamonds
Fuente Paquete ggplot2 (R). Datos de precios reales de diamantes recopilados por Hadley Wickham
Acceso Pública y gratuita: library(ggplot2); data(diamonds)
Documentación ?diamonds en la consola de R
Unidad de observación Un diamante
Tamaño 53.940 diamantes y 10 variables
Precios En dólares estadounidenses (USD)

Cada fila es un diamante puesto a la venta, con su precio y sus cuatro características de calidad, conocidas en el mercado como “las 4 C”: carat (quilates), cut (corte), color y clarity (claridad).

1.2 ¿Dónde está la base de datos?

Esta es una duda muy común: el archivo no se descarga de internet, porque la base viene adentro del paquete ggplot2, que ya está instalado en el computador. Cuando se escribe data(diamonds), R la saca de ahí.

1. Dónde está físicamente en el computador. Está guardada en formato interno de R (.rdb/.rdx), dentro de la carpeta del paquete. Para ver la ruta exacta en cualquier computador:

system.file("data", package = "ggplot2")   # carpeta donde vive la base
.libPaths()                                 # carpeta de todos los paquetes de R

En el computador donde se hizo este informe, la ruta es:

/Users/.../Library/R/x86_64/4.4/library/ggplot2/data/

Esa carpeta cambia según el usuario y el sistema operativo, por eso no se debe escribir la ruta a mano: siempre es mejor cargar la base con data(diamonds).

2. Cómo verla como archivo de Excel. Si se necesita el archivo .csv (por ejemplo, para adjuntarlo o abrirlo en Excel), se exporta así:

write.csv(diamonds, "diamonds.csv", row.names = FALSE)

Eso crea el archivo diamonds.csv (unos 2,6 MB) en la carpeta de trabajo del proyecto, que se puede consultar con getwd().

3. Documentación oficial. Escribiendo ?diamonds en la consola de R aparece la ficha técnica de la base. Su título oficial es “Prices of over 50,000 round cut diamonds” y ahí se describe cada una de las 10 variables. La base fue recopilada por Hadley Wickham, autor de ggplot2, a partir de precios reales publicados por un buscador de diamantes en línea.

1.3 Variables que se analizan

La actividad pide analizar al menos dos variables cualitativas y dos cuantitativas. Aquí se analizan tres cualitativas y dos cuantitativas:

Tipo Variable Nombre en la base Escala de medición
Cualitativa Calidad del corte cut Ordinal (5 categorías)
Cualitativa Claridad (pureza) clarity Ordinal (8 categorías)
Cualitativa Color color Ordinal (7 categorías)
Cuantitativa Precio en dólares price Continua, de razón
Cuantitativa Peso en quilates carat Continua, de razón

Las tres cualitativas son ordinales: sus categorías no son simples nombres, sino que tienen un orden de calidad claro. Por eso sus tablas de frecuencia sí incluyen frecuencias acumuladas (\(N_i\) y \(F_i\)), algo que no tendría sentido en una variable nominal como el género o el color de un carro.

1.4 ¿Qué se hace con cada tipo de variable?

  • Variables cualitativas: no se pueden sumar ni promediar. Se describen con tablas de frecuencia (absolutas, relativas y acumuladas), la moda, la mediana (posible por ser ordinales) y gráficos de barras.
  • Variables cuantitativas: además de la tabla de frecuencias agrupada en intervalos, se calculan medidas de tendencia central (media, mediana, moda), de posición (cuartiles, percentiles), de dispersión (rango, varianza, desviación estándar, coeficiente de variación) y de forma (asimetría y curtosis).

2 Paquetes y carga de los datos

# Si algún paquete no está instalado, ejecute una vez en la consola:
# install.packages(c("ggplot2", "dplyr", "knitr", "kableExtra"))
library(ggplot2)     # contiene la base 'diamonds' y sirve para los gráficos
library(dplyr)       # manipulación de datos
library(knitr)       # tablas
library(kableExtra)  # formato de tablas

La base se carga directamente desde el paquete, así que no hay que descargar ningún archivo ni preocuparse por rutas:

data(diamonds)
diamantes <- as.data.frame(diamonds)

dim(diamantes)      # filas (diamantes) y columnas (variables)
## [1] 53940    10
str(diamantes)      # estructura: tipo de cada variable
## 'data.frame':    53940 obs. of  10 variables:
##  $ carat  : num  0,23 0,21 0,23 0,29 0,31 0,24 0,24 0,26 0,22 0,23 ...
##  $ cut    : Ord.factor w/ 5 levels "Fair"<"Good"<..: 5 4 2 4 2 3 3 3 1 3 ...
##  $ color  : Ord.factor w/ 7 levels "D"<"E"<"F"<"G"<..: 2 2 2 6 7 7 6 5 2 5 ...
##  $ clarity: Ord.factor w/ 8 levels "I1"<"SI2"<"SI1"<..: 2 3 5 4 2 6 7 3 4 5 ...
##  $ depth  : num  61,5 59,8 56,9 62,4 63,3 62,8 62,3 61,9 65,1 59,4 ...
##  $ table  : num  55 61 65 58 58 57 57 55 61 61 ...
##  $ price  : int  326 326 327 334 335 336 336 337 337 338 ...
##  $ x      : num  3,95 3,89 4,05 4,2 4,34 3,94 3,95 4,07 3,87 4 ...
##  $ y      : num  3,98 3,84 4,07 4,23 4,35 3,96 3,98 4,11 3,78 4,05 ...
##  $ z      : num  2,43 2,31 2,31 2,63 2,75 2,48 2,47 2,53 2,49 2,39 ...

La base trae 53.940 diamantes y 10 variables.

Note que R ya reconoce cut, color y clarity como factores ordenados (Ord.factor), es decir, como variables ordinales.

head(diamantes, 5) %>%
  kable(caption = "Primeras 5 filas de la base de datos") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "condensed"),
                latex_options = c("striped", "hold_position"))
Primeras 5 filas de la base de datos
carat cut color clarity depth table price x y z
0,23 Ideal E SI2 61,5 55 326 3,95 3,98 2,43
0,21 Premium E SI1 59,8 61 326 3,89 3,84 2,31
0,23 Good E VS1 56,9 65 327 4,05 4,07 2,31
0,29 Premium I VS2 62,4 58 334 4,20 4,23 2,63
0,31 Good J SI2 63,3 58 335 4,34 4,35 2,75

3 Revisión y limpieza de los datos

Antes de analizar hay que revisar la calidad de los datos. Se verifican tres cosas: datos faltantes, duplicados y valores imposibles.

# 1. Datos faltantes
cat("Total de datos faltantes (NA) en toda la base:", sum(is.na(diamantes)), "\n")
## Total de datos faltantes (NA) en toda la base: 0
# 2. Filas repetidas
cat("Filas duplicadas:", sum(duplicated(diamantes)), "\n")
## Filas duplicadas: 146
# 3. Valores imposibles: un diamante no puede medir 0 mm
cat("Diamantes con alguna dimensión igual a 0 (x, y o z):",
    sum(diamantes$x == 0 | diamantes$y == 0 | diamantes$z == 0), "\n")
## Diamantes con alguna dimensión igual a 0 (x, y o z): 20

Decisiones tomadas:

  1. Datos faltantes: no hay ninguno, así que no hay que imputar ni eliminar nada por esta razón.
  2. Duplicados: hay 146 filas repetidas. Se conservan, porque dos diamantes distintos pueden tener exactamente las mismas características y el mismo precio; no son necesariamente un error de digitación.
  3. Valores imposibles: hay 20 diamantes con largo, ancho o profundidad igual a 0 mm, lo cual es físicamente imposible. Son errores de registro y se eliminan.
diamantes <- diamantes %>%
  filter(x > 0, y > 0, z > 0)

# Etiquetas en español para el corte (se conserva el orden de calidad)
diamantes <- diamantes %>%
  mutate(corte = factor(
    as.character(cut),
    levels = c("Fair", "Good", "Very Good", "Premium", "Ideal"),
    labels = c("Regular (Fair)", "Bueno (Good)",
               "Muy bueno (Very Good)", "Premium", "Ideal"),
    ordered = TRUE))

cat("Diamantes que quedan para el análisis:", nrow(diamantes), "\n")
## Diamantes que quedan para el análisis: 53920

El análisis se hace entonces sobre 53.920 diamantes.

4 Funciones auxiliares

Para no repetir el mismo código en cada variable, se definen unas funciones. Una tabla de frecuencias tiene estas columnas:

# ---- Tabla de frecuencias ----
tabla_frec <- function(x, nombre, ordenar = FALSE, acumuladas = TRUE) {
  x <- x[!is.na(x)]
  t <- as.data.frame(table(x), stringsAsFactors = FALSE)
  names(t) <- c(nombre, "ni")
  if (ordenar) t <- t[order(-t$ni), ]
  t$fi <- round(100 * t$ni / sum(t$ni), 2)
  if (acumuladas) {
    t$Ni <- cumsum(t$ni)
    t$Fi <- round(100 * t$Ni / sum(t$ni), 2)
  }
  total <- t[1, ]; total[1, ] <- NA
  total[[nombre]] <- "Total"; total$ni <- sum(t$ni); total$fi <- 100
  t <- rbind(t, total)
  rownames(t) <- NULL
  names(t)[names(t) == "fi"] <- "fi (%)"
  if (acumuladas) names(t)[names(t) == "Fi"] <- "Fi (%)"
  t
}

mostrar <- function(t, titulo) {
  kable(t, caption = titulo, align = c("l", rep("r", ncol(t) - 1)),
        format.args = list(big.mark = ".", decimal.mark = ",")) %>%
    kable_styling(full_width = FALSE,
                  bootstrap_options = c("striped", "hover", "condensed"),
                  latex_options = c("striped", "hold_position")) %>%
    row_spec(nrow(t), bold = TRUE)
}

# ---- Moda: el valor que más se repite ----
moda <- function(x) {
  x <- x[!is.na(x)]
  tt <- table(x)
  names(tt)[tt == max(tt)]
}

# Moda para variables numéricas.
# Se calcula sin convertir a texto: con options(OutDec = ",") el nombre de la
# tabla sería "0,3" y as.numeric("0,3") daría NA.
moda_num <- function(x) {
  x <- x[!is.na(x)]
  vals <- unique(x)
  vals[which.max(tabulate(match(x, vals)))]
}

# ---- Asimetría y curtosis ----
# Se escriben con las fórmulas de los momentos para no depender de otro paquete.
#   m_k = sum((x - media)^k) / n
#   Asimetría = m3 / m2^(3/2)      Curtosis = m4 / m2^2
skewness <- function(x) {
  x <- x[!is.na(x)]; n <- length(x); m <- mean(x)
  (sum((x - m)^3) / n) / (sum((x - m)^2) / n)^(3/2)
}
kurtosis <- function(x) {
  x <- x[!is.na(x)]; n <- length(x); m <- mean(x)
  (sum((x - m)^4) / n) / ((sum((x - m)^2) / n)^2)
}

# ---- Indicadores estadísticos de una variable cuantitativa ----
indicadores <- function(x) {
  x <- x[!is.na(x)]
  q <- quantile(x, c(0.25, 0.50, 0.75, 0.90))
  data.frame(
    Indicador = c("n (datos válidos)", "Media", "Mediana", "Moda",
                  "Mínimo", "Máximo", "Rango",
                  "Cuartil 1 (Q1)", "Cuartil 3 (Q3)",
                  "Rango intercuartílico (RIC)",
                  "Percentil 90", "Varianza", "Desviación estándar",
                  "Coeficiente de variación (%)",
                  "Coeficiente de asimetría", "Curtosis (exceso)"),
    Valor = c(length(x), mean(x), median(x), moda_num(x),
              min(x), max(x), max(x) - min(x),
              q[1], q[3], q[3] - q[1], q[4],
              var(x), sd(x), 100 * sd(x) / mean(x),
              skewness(x), kurtosis(x) - 3)
  )
}

# ---- Tabla de frecuencias por intervalos ----
tabla_intervalos <- function(x, cortes, etiquetas, nombre) {
  x <- x[!is.na(x)]
  clase <- cut(x, breaks = cortes, labels = etiquetas,
               right = TRUE, include.lowest = TRUE)
  tabla_frec(clase, nombre, ordenar = FALSE, acumuladas = TRUE)
}

# ---- Formato de números para el texto ----
fmt <- function(x, d = 2) format(round(x, d), big.mark = ".", decimal.mark = ",",
                                 nsmall = 0, scientific = FALSE)

# Variante con dos decimales fijos, para los pesos en quilates (1 -> "1,00")
fmt_q <- function(x) format(round(x, 2), nsmall = 2,
                            decimal.mark = ",", big.mark = ".")

# Formato de los números de los ejes de los gráficos
fmt_eje <- function(x) format(x, big.mark = ".", scientific = FALSE)

5 Análisis de las variables cualitativas

5.1 Calidad del corte

¿Qué mide? El corte indica qué tan bien fue tallado el diamante, lo que determina cuánta luz refleja. Es una variable cualitativa ordinal con 5 categorías, de peor a mejor: Regular (Fair) < Bueno (Good) < Muy bueno (Very Good) < Premium < Ideal.

tab_corte <- tabla_frec(diamantes$corte, "Calidad del corte")
mostrar(tab_corte,
        "Tabla 1. Distribución de los diamantes según la calidad del corte")
Tabla 1. Distribución de los diamantes según la calidad del corte
Calidad del corte ni fi (%) Ni Fi (%)
Regular (Fair) 1.609 2,98 1.609 2,98
Bueno (Good) 4.902 9,09 6.511 12,08
Muy bueno (Very Good) 12.081 22,41 18.592 34,48
Premium 13.780 25,56 32.372 60,04
Ideal 21.548 39,96 53.920 100,00
Total 53.920 100,00
diamantes %>%
  count(corte) %>% mutate(p = n / sum(n)) %>%
  ggplot(aes(x = corte, y = n, fill = corte)) +
  geom_col(show.legend = FALSE, width = 0.7) +
  geom_text(aes(label = paste0(format(n, big.mark = "."), "\n(",
                               round(100 * p, 1), "%)")),
            vjust = -0.3, size = 3.2, lineheight = 0.9) +
  scale_fill_brewer(palette = "Blues") +
  scale_y_continuous(expand = expansion(mult = c(0, 0.18))) +
  labs(title = "Diamantes según la calidad del corte",
       x = "Calidad del corte (de menor a mayor)", y = "Número de diamantes") +
  theme_minimal()

Indicadores:

  • Moda: Ideal — es la categoría más frecuente.
  • Mediana: por ser ordinal se puede calcular. Es la categoría donde \(F_i\) alcanza el 50 %: Premium.

Interpretación: la distribución está concentrada en las calidades altas. El corte Ideal es el más frecuente (40 %) y, sumado a Premium y Muy bueno, concentra cerca del 87,9 % del total. En cambio, el corte Regular (Fair) apenas representa el 3 %. Esto tiene sentido comercial: los diamantes que llegan al mercado ya pasaron por un proceso de tallado profesional, y un corte deficiente destruye valor, así que es raro.

5.2 Claridad (pureza)

¿Qué mide? La claridad indica qué tan libre de impurezas internas está el diamante. Es ordinal, con 8 categorías de peor a mejor:

Código Significado
I1 Con inclusiones visibles (la peor)
SI2, SI1 Inclusiones pequeñas
VS2, VS1 Inclusiones muy pequeñas
VVS2, VVS1 Inclusiones sumamente pequeñas
IF Internamente impecable (la mejor)
tab_clar <- tabla_frec(diamantes$clarity, "Claridad")
mostrar(tab_clar, "Tabla 2. Distribución de los diamantes según la claridad")
Tabla 2. Distribución de los diamantes según la claridad
Claridad ni fi (%) Ni Fi (%)
I1 738 1,37 738 1,37
SI2 9.185 17,03 9.923 18,40
SI1 13.063 24,23 22.986 42,63
VS2 12.254 22,73 35.240 65,36
VS1 8.170 15,15 43.410 80,51
VVS2 5.066 9,40 48.476 89,90
VVS1 3.654 6,78 52.130 96,68
IF 1.790 3,32 53.920 100,00
Total 53.920 100,00
diamantes %>%
  count(clarity) %>% mutate(p = n / sum(n)) %>%
  ggplot(aes(x = clarity, y = n)) +
  geom_col(fill = "#2A9D8F", width = 0.7) +
  geom_text(aes(label = paste0(round(100 * p, 1), "%")),
            vjust = -0.35, size = 3.3) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(title = "Diamantes según la claridad",
       x = "Claridad (de peor a mejor)", y = "Número de diamantes") +
  theme_minimal()

Indicadores:

  • Moda: SI1.
  • Mediana: VS2.

Interpretación: la distribución tiene forma de campana asimétrica: las categorías intermedias (SI1, VS2, SI2, VS1) concentran la mayoría de los diamantes, mientras que los extremos son escasos. Solo el 1,4 % tiene la peor claridad (I1) y apenas el 3,3 % alcanza la mejor (IF). Según la columna \(F_i\), el 65,4 % de los diamantes tiene claridad VS2 o inferior. La lectura de mercado es clara: los diamantes perfectos son rarezas, y el grueso del comercio ocurre en calidades medias.

5.3 Color

¿Qué mide? En los diamantes blancos, el color se mide por ausencia de color: la escala va de D (incoloro, el mejor) hasta J (con tono amarillento, el peor de esta base).

tab_color <- tabla_frec(diamantes$color, "Color")
mostrar(tab_color, "Tabla 3. Distribución de los diamantes según el color")
Tabla 3. Distribución de los diamantes según el color
Color ni fi (%) Ni Fi (%)
D 6.774 12,56 6.774 12,56
E 9.797 18,17 16.571 30,73
F 9.538 17,69 26.109 48,42
G 11.284 20,93 37.393 69,35
H 8.298 15,39 45.691 84,74
I 5.421 10,05 51.112 94,79
J 2.808 5,21 53.920 100,00
Total 53.920 100,00
diamantes %>%
  count(color) %>% mutate(p = n / sum(n)) %>%
  ggplot(aes(x = color, y = n)) +
  geom_col(fill = "#E9C46A", color = "#B8860B", width = 0.7) +
  geom_text(aes(label = paste0(round(100 * p, 1), "%")),
            vjust = -0.35, size = 3.3) +
  scale_y_continuous(expand = expansion(mult = c(0, 0.15))) +
  labs(title = "Diamantes según el color",
       x = "Color (D = incoloro, el mejor;  J = el más amarillento)",
       y = "Número de diamantes") +
  theme_minimal()

Indicadores:

  • Moda: color G.
  • Mediana: color G.

Interpretación: el color más común es el G (20,9 %), una calidad intermedia. La frecuencia disminuye hacia los extremos: los incoloros perfectos (D) son el 12,6 % y los más amarillentos (J) solo el 5,2 %. Igual que con la claridad, el mercado se concentra en calidades medias.

6 Análisis de las variables cuantitativas

En las variables cuantitativas hay demasiados valores distintos para hacer una tabla valor por valor, así que los datos se agrupan en intervalos (clases).

La regla de Sturges, \(k = 1 + 3{,}322 \log_{10}(n)\), sugiere cuántos intervalos de igual amplitud usar:

n <- nrow(diamantes)
k <- 1 + 3.322 * log10(n)
cat("n =", n, "  ->  k sugerido por Sturges =", round(k, 1), "intervalos\n")
## n = 53920   ->  k sugerido por Sturges = 16,7 intervalos

Sturges sugiere unos 17 intervalos de igual amplitud. Sin embargo, las dos variables son muy asimétricas (la mayoría de los diamantes son pequeños y baratos, y unos pocos valen una fortuna). Con intervalos de igual amplitud, casi todos los diamantes caerían en las primeras clases y las últimas quedarían casi vacías. Por eso se usan intervalos con sentido comercial (rangos de precio y de peso que un joyero reconocería), que resumen mejor la información.

6.1 Precio

¿Qué mide? El precio de venta del diamante en dólares (USD). Es una variable cuantitativa continua de razón.

6.1.1 Tabla de frecuencias

tab_precio <- tabla_intervalos(
  diamantes$price,
  cortes    = c(-Inf, 1000, 2500, 5000, 10000, Inf),
  etiquetas = c("Hasta 1.000", "Más de 1.000 a 2.500", "Más de 2.500 a 5.000",
                "Más de 5.000 a 10.000", "Más de 10.000"),
  nombre    = "Precio (USD)"
)
mostrar(tab_precio,
        "Tabla 4. Distribución de los diamantes según el precio (USD)")
Tabla 4. Distribución de los diamantes según el precio (USD)
Precio (USD) ni fi (%) Ni Fi (%)
Hasta 1.000 14.524 26,94 14.524 26,94
Más de 1.000 a 2.500 13.015 24,14 27.539 51,07
Más de 2.500 a 5.000 11.678 21,66 39.217 72,73
Más de 5.000 a 10.000 9.489 17,60 48.706 90,33
Más de 10.000 5.214 9,67 53.920 100,00
Total 53.920 100,00

6.1.2 Indicadores estadísticos

ind_precio <- indicadores(diamantes$price)
ind_precio %>% mutate(Valor = round(Valor, 2)) %>%
  kable(caption = "Tabla 5. Indicadores estadísticos del precio (USD)",
        format.args = list(big.mark = ".", decimal.mark = ",")) %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "condensed"),
                latex_options = c("striped", "hold_position"))
Tabla 5. Indicadores estadísticos del precio (USD)
Indicador Valor
n (datos válidos) 53.920,00
Media 3.930,99
Mediana 2.401,00
Moda 605,00
Mínimo 326,00
Máximo 18.823,00
Rango 18.497,00
Cuartil 1 (Q1) 949,00
Cuartil 3 (Q3) 5.323,25
Rango intercuartílico (RIC) 4.374,25
Percentil 90 9.818,10
Varianza 15.898.405,35
Desviación estándar 3.987,28
Coeficiente de variación (%) 101,43
Coeficiente de asimetría 1,62
Curtosis (exceso) 2,18
ggplot(diamantes, aes(x = price)) +
  geom_histogram(binwidth = 500, boundary = 0,
                 fill = "#264653", color = "white") +
  geom_vline(aes(xintercept = mean(price), color = "Media"),
             linewidth = 1, linetype = "dashed") +
  geom_vline(aes(xintercept = median(price), color = "Mediana"), linewidth = 1) +
  scale_color_manual(values = c(Media = "#E76F51", Mediana = "#2A9D8F"),
                     name = NULL) +
  scale_x_continuous(labels = fmt_eje) +
  labs(title = "Histograma del precio de los diamantes",
       x = "Precio (USD)", y = "Número de diamantes") +
  theme_minimal() + theme(legend.position = "top")

ggplot(diamantes, aes(x = price, y = "")) +
  geom_boxplot(fill = "#8ECAE6", outlier.color = "#E76F51", outlier.alpha = 0.2) +
  scale_x_continuous(labels = fmt_eje) +
  labs(title = "Diagrama de caja del precio", x = "Precio (USD)", y = NULL) +
  theme_minimal()

6.1.3 Interpretación

  • Tendencia central: el precio promedio es de USD 3.930,99, pero la mediana es USD 2.401: la mitad de los diamantes cuesta esa cantidad o menos. El precio más frecuente (moda) es USD 605. Que la media sea 1,6 veces la mediana revela que unos pocos diamantes carísimos (hasta USD 18.823) empujan el promedio hacia arriba. La mediana describe mejor al diamante típico.
  • Posición: el 25 % más barato cuesta hasta USD 949 (Q1) y el 75 % cuesta hasta USD 5.323 (Q3). El 50 % central se mueve en un rango de USD 4.374 (el RIC). Solo el 10 % supera los USD 9.818.
  • Dispersión: la desviación estándar (USD 3.987,28) es mayor que la media, y el coeficiente de variación llega a 101,4 %. Como regla práctica, un CV superior al 30 % ya indica alta dispersión; aquí es extrema. Hablar de “el precio promedio de un diamante” es, por lo tanto, poco informativo.
  • Forma: la asimetría es positiva (1,62), es decir, hay sesgo a la derecha: muchos diamantes baratos y una cola larga de diamantes caros. La curtosis en exceso es 2,18 (mayor que 0, distribución leptocúrtica): más valores extremos de los que tendría una distribución normal. El diagrama de caja lo confirma con la enorme cantidad de puntos atípicos a la derecha.
  • Lectura de la tabla 4: el 72,7 % de los diamantes cuesta USD 5.000 o menos, mientras que los de más de USD 10.000 son apenas el 9,7 %.

6.2 Peso en quilates

¿Qué mide? El peso del diamante en quilates (1 quilate = 0,2 gramos). Es cuantitativa continua de razón.

6.2.1 Tabla de frecuencias

tab_carat <- tabla_intervalos(
  diamantes$carat,
  cortes    = c(-Inf, 0.3, 0.5, 1.0, 1.5, 2.0, Inf),
  etiquetas = c("Hasta 0,30", "Más de 0,30 a 0,50", "Más de 0,50 a 1,00",
                "Más de 1,00 a 1,50", "Más de 1,50 a 2,00", "Más de 2,00"),
  nombre    = "Peso (quilates)"
)
mostrar(tab_carat,
        "Tabla 6. Distribución de los diamantes según el peso en quilates")
Tabla 6. Distribución de los diamantes según el peso en quilates
Peso (quilates) ni fi (%) Ni Fi (%)
Hasta 0,30 4.203 7,79 4.203 7,79
Más de 0,30 a 0,50 14.729 27,32 18.932 35,11
Más de 0,50 a 1,00 17.502 32,46 36.434 67,57
Más de 1,00 a 1,50 12.051 22,35 48.485 89,92
Más de 1,50 a 2,00 3.552 6,59 52.037 96,51
Más de 2,00 1.883 3,49 53.920 100,00
Total 53.920 100,00

6.2.2 Indicadores estadísticos

ind_carat <- indicadores(diamantes$carat)
ind_carat %>% mutate(Valor = round(Valor, 3)) %>%
  kable(caption = "Tabla 7. Indicadores estadísticos del peso en quilates",
        format.args = list(big.mark = ".", decimal.mark = ",")) %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "condensed"),
                latex_options = c("striped", "hold_position"))
Tabla 7. Indicadores estadísticos del peso en quilates
Indicador Valor
n (datos válidos) 53.920,000
Media 0,798
Mediana 0,700
Moda 0,300
Mínimo 0,200
Máximo 5,010
Rango 4,810
Cuartil 1 (Q1) 0,400
Cuartil 3 (Q3) 1,040
Rango intercuartílico (RIC) 0,640
Percentil 90 1,510
Varianza 0,224
Desviación estándar 0,474
Coeficiente de variación (%) 59,395
Coeficiente de asimetría 1,116
Curtosis (exceso) 1,255
ggplot(diamantes, aes(x = carat)) +
  geom_histogram(binwidth = 0.05, boundary = 0,
                 fill = "#6A4C93", color = "white") +
  geom_vline(aes(xintercept = mean(carat), color = "Media"),
             linewidth = 1, linetype = "dashed") +
  geom_vline(aes(xintercept = median(carat), color = "Mediana"), linewidth = 1) +
  scale_color_manual(values = c(Media = "#E76F51", Mediana = "#2A9D8F"),
                     name = NULL) +
  coord_cartesian(xlim = c(0, 3)) +
  labs(title = "Histograma del peso en quilates (hasta 3 quilates)",
       x = "Peso (quilates)", y = "Número de diamantes") +
  theme_minimal() + theme(legend.position = "top")

ggplot(diamantes, aes(x = carat, y = "")) +
  geom_boxplot(fill = "#C8B6E2", outlier.color = "#6A4C93", outlier.alpha = 0.2) +
  labs(title = "Diagrama de caja del peso en quilates",
       x = "Peso (quilates)", y = NULL) +
  theme_minimal()

6.2.3 Interpretación

  • Tendencia central: el peso promedio es de 0,8 quilates y la mediana es 0,7. La moda es 0,3 quilates. Aquí la media y la mediana están mucho más cerca que en el precio, así que la media es un resumen más aceptable, aunque sigue habiendo sesgo.
  • Posición: el 25 % más pequeño pesa hasta 0,4 quilates y el 75 % hasta 1,04. El 10 % más grande supera los 1,51 quilates, y el máximo llega a 5,01.
  • Dispersión: desviación estándar de 0,47 quilates y CV de 59,4 %: alta dispersión, pero bastante menor que la del precio (101,4 %). Esto ya anticipa algo importante: el precio varía mucho más que el tamaño, porque el precio no depende solo del peso.
  • Forma: asimetría positiva (1,12) y curtosis en exceso de 1,26; de nuevo, sesgo a la derecha y colas pesadas.
  • Un detalle interesante del histograma: se ven picos en valores “redondos” (0,3; 0,5; 0,7; 1,0; 1,5 quilates) y huecos justo antes de ellos. No es casualidad: los talladores sacrifican material para llegar a esos pesos psicológicos de venta, porque un diamante de 1,00 quilate se vende mucho mejor que uno de 0,97. La estadística descriptiva alcanza a revelar esa práctica del oficio.
  • Lectura de la tabla 6: el 67,6 % de los diamantes pesa 1 quilate o menos.

7 Análisis complementario: cruce de variables

7.1 Precio según la calidad del corte

Hasta aquí cada variable se analizó por separado. Ahora se cruzan una cualitativa y una cuantitativa.

diamantes %>%
  group_by(Corte = corte) %>%
  summarise(Diamantes = n(),
            `Precio mediano` = median(price),
            `Precio medio` = round(mean(price), 0),
            `Quilates (mediana)` = median(carat)) %>%
  kable(caption = "Tabla 8. Precio (USD) y peso según la calidad del corte",
        format.args = list(big.mark = ".", decimal.mark = ",")) %>%
  kable_styling(full_width = FALSE,
                bootstrap_options = c("striped", "hover", "condensed"),
                latex_options = c("striped", "hold_position"))
Tabla 8. Precio (USD) y peso según la calidad del corte
Corte Diamantes Precio mediano Precio medio Quilates (mediana)
Regular (Fair) 1.609 3.282,0 4.358 1,000
Bueno (Good) 4.902 3.050,5 3.926 0,820
Muy bueno (Very Good) 12.081 2.647,0 3.982 0,710
Premium 13.780 3.182,0 4.580 0,855
Ideal 21.548 1.809,5 3.457 0,540
ggplot(diamantes, aes(x = corte, y = price, fill = corte)) +
  geom_boxplot(show.legend = FALSE, outlier.alpha = 0.1) +
  scale_fill_brewer(palette = "Blues") +
  scale_y_continuous(labels = fmt_eje) +
  labs(title = "Precio según la calidad del corte",
       x = "Calidad del corte (de menor a mayor)", y = "Precio (USD)") +
  theme_minimal()

7.1.1 Un resultado que parece un error (pero no lo es)

La tabla 8 muestra algo que contradice la intuición: los diamantes de peor corte (Regular/Fair) tienen un precio mediano de USD 3.282, mientras que los de mejor corte (Ideal) cuestan apenas USD 1.810. ¿El mejor corte se vende más barato?

La explicación está en la última columna: los diamantes de corte Regular pesan en mediana 1,00 quilates y los de corte Ideal solo 0,54. Es decir, los diamantes mal cortados de esta base son mucho más grandes, y el peso influye tanto en el precio que tapa completamente el efecto del corte.

Esto ocurre porque tallar un diamante con corte Ideal exige desperdiciar más material: para lograr las proporciones perfectas hay que sacrificar peso. Cuando la piedra en bruto es grande y valiosa, el joyero prefiere conservar el tamaño aunque el corte quede regular.

En estadística esto se llama variable de confusión: el peso está detrás de los dos fenómenos y distorsiona la comparación. Al comparar diamantes de un tamaño parecido, el efecto real del corte aparece:

diamantes %>%
  # se comparan solo diamantes de tamaño parecido
  filter(carat >= 0.9, carat <= 1.1) %>%
  group_by(Corte = corte) %>%
  summarise(Diamantes = n(),
            `Precio mediano` = median(price),
            `Quilates (mediana)` = median(carat)) %>%
  kable(caption = paste("Tabla 9. Precio (USD) según el corte, comparando",
                        "solo diamantes de 0,9 a 1,1 quilates"),
        format.args = list(big.mark = ".", decimal.mark = ",")) %>%
  kable_styling(full_width = FALSE,
                bootstrap_options = c("striped", "hover", "condensed"),
                latex_options = c("striped", "hold_position"))
Tabla 9. Precio (USD) según el corte, comparando solo diamantes de 0,9 a 1,1 quilates
Corte Diamantes Precio mediano Quilates (mediana)
Regular (Fair) 589 3.730,0 1,00
Bueno (Good) 1.483 4.312,0 1,00
Muy bueno (Very Good) 2.715 4.690,0 1,01
Premium 2.882 4.672,0 1,01
Ideal 2.656 5.220,5 1,02

Ahora sí: a igual tamaño, mejor corte significa mayor precio. Esta es la lección más importante del informe: una tabla descriptiva mal leída puede llevar a una conclusión falsa; siempre hay que preguntarse qué otra variable puede estar detrás.

7.2 Relación entre peso y precio

ggplot(diamantes, aes(x = carat, y = price)) +
  geom_point(alpha = 0.08, color = "#264653") +
  geom_smooth(method = "loess", se = FALSE, color = "#E76F51", linewidth = 1) +
  scale_y_continuous(labels = fmt_eje) +
  labs(title = "Relación entre el peso y el precio",
       subtitle = "Cada punto es un diamante; la curva muestra la tendencia",
       x = "Peso (quilates)", y = "Precio (USD)") +
  theme_minimal()

cat("Coeficiente de correlación de Pearson (peso vs. precio):",
    round(cor(diamantes$carat, diamantes$price), 3), "\n")
## Coeficiente de correlación de Pearson (peso vs. precio): 0,922

Interpretación: la correlación es 0,922, muy cercana a 1: el peso y el precio están fuertemente relacionados de forma positiva. Pero la nube de puntos muestra que la relación no es una línea recta: es curva y se abre en abanico. A medida que el diamante crece, el precio sube cada vez más rápido y además se vuelve más impredecible (dos diamantes de 2 quilates pueden tener precios muy distintos según su color y claridad). Por eso el precio tiene un coeficiente de variación tan alto.

8 Conclusiones

  1. Sobre la calidad (variables cualitativas): el mercado de diamantes está sesgado hacia las calidades altas de corte (el 40 % tiene corte Ideal), pero concentrado en calidades medias de claridad y color. La claridad impecable (IF) solo alcanza el 3,3 % de los diamantes, y el color incoloro perfecto (D) el 12,6 %.

  2. Sobre el precio: es una variable extremadamente dispersa y muy asimétrica a la derecha (CV = 101,4 %, asimetría = 1,62). El diamante típico cuesta USD 2.401 (mediana), bastante menos que el promedio de USD 3.931.

  3. Sobre el peso: el diamante típico pesa 0,7 quilates y el 67,6 % pesa 1 quilate o menos. El histograma delata una práctica comercial: los pesos se concentran en cifras redondas de venta.

  4. Sobre la relación entre variables: el peso explica gran parte del precio (correlación de 0,922), pero la relación es no lineal y se vuelve más dispersa en los diamantes grandes.

  5. Lección estadística principal: en distribuciones asimétricas y con valores atípicos, la media engaña. Es mejor reportar la mediana y los cuartiles, acompañados de medidas de dispersión y de forma. Y sobre todo, el caso del corte demuestra que una comparación entre grupos puede invertirse cuando se controla una variable de confusión: los diamantes de mejor corte parecían más baratos solo porque eran más pequeños.

  6. Recomendación para un comprador: dado que el precio se dispara con el peso pero el corte influye menos en él, conviene bajar un poco en peso y subir en calidad de corte: se obtiene un diamante que brilla más por un precio considerablemente menor.