Introducción

El presente trabajo tiene como objetivo realizar un análisis exploratorio de datos (EDA) utilizando R Studio en conjunto con Apache Spark mediante la librería sparklyr. Esta actividad busca poner en práctica la conexión entre R y Spark y aplicar técnicas de exploración de datos.

Para el análisis se utiliza el conjunto de datos “Sample - Superstore” https://www.kaggle.com/datasets/vivek468/superstore-dataset-final. Este archivo contiene información detallada sobre ventas de una tienda minorista, incluyendo variables como:

  • Identificadores de pedidos y clientes.
  • Fechas de orden y envío.
  • Segmentos de clientes y regiones geográficas.
  • Categorías y subcategorías de productos.
  • Métricas de negocio como ventas, cantidad, descuento y ganancia (profit).

Este dataset permite identificar tendencias mensuales, patrones estacionales, y posibles correlaciones entre variables comerciales.

1. Cargar librerías necesarias

Se realiza el cargue de las librerías necesarias para la ejecución del cídogo, estas tienen las siguientes funciones: * sparklyr: Conecta R con Apache Spark para procesar datos grandes. * dplyr: Manipula y transforma datos fácilmente con funciones intuitivas. * ggplot2: Crea gráficos avanzados y personalizables. * reshape2: Transforma datos entre formatos anchos y largos para análisis y gráficos.

library(sparklyr)
library(dplyr)
library(ggplot2)
library(reshape2)

2. Conectar con Apache Spark

Establece una conexión a un clúster Spark en modo local

sc <- spark_connect(master = "local")

3. Leer archivo CSV en R y limpiar nombres de columnas

El código carga un archivo CSV llamado Sample - Superstore.csv en R, reemplaza los espacios en los nombres de las columnas por guiones bajos para facilitar su uso, y muestra las primeras filas del dataset para verificar que se importó correctamente.

ventas_local <- read.csv("C:/CodigoR/Sample - Superstore.csv", 
                         stringsAsFactors = FALSE)

# Reemplazar espacios por guiones bajos en los nombres de columnas
colnames(ventas_local) <- gsub(" ", "_", colnames(ventas_local))

# Vista preliminar para confirmar
head(ventas_local)

4. Enviar el dataset limpio a Spark

Se Copia el data frame local ‘ventas_local’ al entorno de Spark y se guarda como ‘ventas’

ventas <- copy_to(sc, ventas_local, overwrite = TRUE)

5. Análisis exploratorio

5.1 Vista preliminar, número de filas y columnas

Este código realiza una exploración inicial del dataset ventas en Spark: muestra las primeras 10 filas, obtiene el número total de filas, y lista los nombres de las columnas.

# Vista preliminar
ventas %>% head(10) %>% collect()
# Número de filas
ventas %>% sdf_nrow()
## [1] 9994
# Variables disponibles
colnames(ventas)
##  [1] "Row_ID"        "Order_ID"      "Order_Date"    "Ship_Date"    
##  [5] "Ship_Mode"     "Customer_ID"   "Customer_Name" "Segment"      
##  [9] "Country"       "City"          "State"         "Postal_Code"  
## [13] "Region"        "Product_ID"    "Category"      "Sub_Category" 
## [17] "Product_Name"  "Sales"         "Quantity"      "Discount"     
## [21] "Profit"

5.2 Estadísticas descriptivas básicas

Se realizan cálculos estadísticos descriptivos (como count, mean, stddev, min, max) para cada columna del dataset en Spark y se traen los resultados al entorno local de R como un data frame

#ventas %>% sdf_describe() %>% collect()

# Obtener estadísticas solo de variables numéricas
ventas %>%
  select(Sales, Profit, Quantity, Discount) %>%  # Selecciona solo columnas numéricas
  sdf_describe() %>%                             # Calcula estadísticas básicas en Spark
  collect()                                      # Trae los resultados al entorno local de R

5.3 Distribución de las ventas

Se selecciona solo la columna ‘Sales’ del data frame ‘ventas’ y se asegura de que los datos estén en el entorno local (collect), luego se convierte la columna ‘Sales’ a tipo numérico

ventas_dist <- ventas %>%
  select(Sales) %>%                # Se selecciona la columna 'Sales'
  collect() %>%                    # Se traen los datos al entorno local
  mutate(Sales = as.numeric(Sales))  # Se convierte 'Sales' a numérico

# Se crea un histograma con ggplot para visualizar la distribución de ventas
ggplot(ventas_dist, aes(x = Sales)) +           # Establece 'Sales' como variable en el eje X
  geom_histogram(bins = 50,                     # Usa 50 intervalos (bins) en el histograma
                 fill = "skyblue",              
                 color = "black") +             
  theme_minimal() +                             # Se aplica un tema al gráfico
  labs(title = "Distribución de Ventas",        
       x = "Ventas",                            # Etiqueta del eje X
       y = "Frecuencia")                        # Etiqueta del eje Y

En el anterior grafico se observa que el mayor número de frecuencias están en compras de bajo costo, lo que es consecuente con el origen del conjunto de datos el cual es una tienda minorista, a medida que el valor de la venta aumenta su frecuencia se reduce drásticamente.

5.4 Resúmenes por períodos de tiempo

Este fragmento de código toma los datos de ventas (desde Spark), convierte las fechas al formato correcto en R, extrae el año y el mes, y luego calcula el total de ventas por mes. Finalmente, muestra las primeras filas de ese resumen mensual.

ventas_mensuales <- ventas %>%
  select(Order_Date, Sales) %>%                       # Se Seleccionan solo las columnas de fecha y ventas
  collect() %>%                                       # Se trae los datos desde Spark al entorno local de R
  mutate(
    Order_Date = as.Date(Order_Date, format = "%m/%d/%Y"),  # Se convierte la columna 'Order_Date' a tipo fecha, usando el formato mes/día/año
    year = as.numeric(format(Order_Date, "%Y")),            # Se extrae el año de la fecha
    month = as.numeric(format(Order_Date, "%m"))            # Se extrae el mes de la fecha
  ) %>%
  group_by(year, month) %>%                           # Se agrupa los datos por año y mes
  summarise(
    total_ventas = sum(Sales),                        # Se suman las ventas dentro de cada grupo (año y mes)
    .groups = "drop"                                  # Se elimina la agrupación después del resumen
  ) %>%
  arrange(year, month)                                # Se ordena los resultados cronológicamente por año y mes

head(ventas_mensuales)  # Se muestran las primeras filas del data frame con las ventas mensuales

6. Visualización de tendencias

Este gráfico de líneas muestra la evolución de las ventas totales por mes.

ggplot(ventas_mensuales,
       aes(x = as.Date(paste(year, month, "01", sep = "-")),
           y = total_ventas)) +
  geom_line(color = "blue", size = 1) +
  geom_point(color = "red") +
  theme_minimal() +
  scale_x_date(date_labels = "%Y-%m", date_breaks = "3 months") +  # Formato de fecha: Año-Mes
  labs(title = "Tendencia de Ventas Mensuales",
       x = "Fecha (Año-Mes)",
       y = "Total de Ventas") +
  theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust = 1))  # Gira las etiquetas del eje X

En el gráfico de líneas se observan comportamientos cíclicos que se repiten cada año. Durante los primeros meses del año, las ventas tienden a alcanzar sus valores mínimos. A partir de marzo se produce un repunte temporal, que no se mantiene, ya que entre marzo y agosto se evidencia una disminución gradual en las ventas, aunque no tan pronunciada como la de los meses iniciales. A partir de septiembre y hasta diciembre, se registran los valores más altos del año, con una leve caída recurrente en octubre. Este patrón se repite consistentemente en el período analizado, que abarca desde 2014 hasta 2018. Además, el análisis revela una tendencia creciente en las ventas a lo largo del tiempo. Por ejemplo, en 2014 el valor máximo mensual rondaba los 76,000, mientras que en 2018 se superaron los 125,000. Esto indica un crecimiento sostenido en las ventas durante los años analizados. En resumen, se identifican tanto patrones estacionales que se repiten cada año como una tendencia positiva a largo plazo en el volumen de ventas.


7. Posibles correlaciones entre variables

El segmento de código calcula la matriz de correlación entre varias variables numéricas del dataset ventas, que inicialmente está almacenado en Spark.

ventas_corr <- ventas %>%
  select(Sales, Profit, Quantity, Discount) %>%     # Se seleccionan solo las columnas numéricas relevantes
  collect() %>%                                     # Se traen los datos desde Spark al entorno local de R
  mutate(across(everything(), as.numeric))          # Se convierten todas las columnas a tipo numérico

# Calcular matriz de correlación con 2 decimales
cor_matrix <- cor(ventas_corr, use = "complete.obs")  # Se calcula la matriz de correlación, ignorando valores faltantes (NA)
round(cor_matrix, 2)                                  # Se redondea la matriz resultante a 2 decimales para mejor lectura
##          Sales Profit Quantity Discount
## Sales     1.00   0.48     0.20    -0.03
## Profit    0.48   1.00     0.07    -0.22
## Quantity  0.20   0.07     1.00     0.01
## Discount -0.03  -0.22     0.01     1.00

Los resultados obtenidos confirman lo identificado en el análisis de correlaciones. La correlación positiva más fuerte se observa entre ventas y ganancias, con un valor de 0.48, lo que indica una relación moderadamente positiva entre ambas variables. Le sigue la correlación entre ganancias y cantidad vendida, con un valor de 0.20, lo que sugiere una relación más débil pero aún positiva. En contraste, las correlaciones más débiles o negativas se presentan entre ventas y descuentos con un valor de –0.03, lo cual indica prácticamente ninguna relación entre ambas variables. Asimismo, la correlación entre ganancias y descuentos es de –0.22, lo que refleja una relación negativa leve, es decir, a mayor descuento, tienden a disminuir las ganancias.

7.1 Gráfico de correlación (heatmap)

Este fragmento genera un mapa de calor (heatmap) visualizando la matriz de correlación entre variables numéricas, usando ggplot2.

# Calcular la matriz de correlación nuevamente (por seguridad)
matriz_corr <- cor(ventas_corr, use = "complete.obs")

# Convertir en formato largo para ggplot
matriz_corr_melt <- melt(matriz_corr)

# Graficar heatmap de correlación con valores
ggplot(matriz_corr_melt, aes(x = Var1, y = Var2, fill = value)) +
  geom_tile(color = "white") +
  geom_text(aes(label = round(value, 2)), color = "black", size = 4) +
  scale_fill_gradient2(low = "red", high = "blue", mid = "white", 
                       midpoint = 0, limit = c(-1, 1), space = "Lab",
                       name = "Correlación") +
  theme_minimal() +
  labs(title = "Mapa de calor de correlación",
       x = "Variables", y = "Variables") +
  theme(axis.text.x = element_text(angle = 45, vjust = 1, hjust = 1))

7.2 Diagrama de dispersión entre las variables más correlacionadas

El segmento de código extrae las variables Sales y Profit del dataset, las trae al entorno local y luego crea un gráfico de dispersión (scatter plot) para visualizar la relación entre ventas y ganancias.

# Extraer variables más correlacionadas (Sales y Profit)
scatter_data <- ventas %>%
  select(Sales, Profit) %>%
  collect() %>%
  mutate(across(everything(), as.numeric))

# Graficar scatter plot
ggplot(scatter_data, aes(x = Sales, y = Profit)) +
  geom_point(alpha = 0.5, color = "blue") +
  theme_minimal() +
  labs(title = "Relación entre Sales (Ventas) y Profit (Ganancia)",
       x = "Sales (Ventas)",
       y = "Profit (Ganancia)")

Se observa una dispersión significativa en la relación entre las dos variables, sin embargo, también es evidente una relación positiva entre las ventas y las ganancias: a mayor valor de venta, mayor tiende a ser la ganancia. En el gráfico se identifican algunos valores atípicos, los cuales deben ser analizados con mayor detalle, ya que podrían estar asociados a descuentos elevados o a posibles problemas de calidad en los datos.

7.3 Diagrama de dispersión entre Ganancias y Descuento

Este segmento de código visualiza con un gráfico de dispersión la relación entre los descuentos aplicados (Discount) y las ventas (Sales). Ayuda a identificar si hay algún patrón o tendencia, por ejemplo, si mayores descuentos están relacionados con mayores o menores ventas.

# Extraer variables Profit y Discount
scatter_profit_discount <- ventas %>%
  select(Profit, Discount) %>%                          # Selecciona ganancias y descuentos
  collect() %>%
  mutate(across(everything(), as.numeric))              # Asegura que ambas columnas sean numéricas

# Graficar scatter plot
ggplot(scatter_profit_discount, aes(x = Discount, y = Profit)) +  # Mapea Discount al eje X y Profit al eje Y
  geom_point(alpha = 0.5, color = "darkgreen") +                  # Puntos con transparencia y color verde oscuro
  theme_minimal() +
  labs(title = "Relación entre Discount (Descuento) y Profit (Ganancia)",
       x = "Discount (Descuento)",
       y = "Profit (Ganancia)")

  • En la gráfica se puede observar que cuando aumentan los descuentos las ganancias disminuyen, por el contrario, cuando reducen o son nulos los descuentos las ganancias aumenta, lo que demuestra una correlación negativa, el aumento de uno genera la reducción del otro.

8. Cerrar la conexión con Spark

spark_disconnect(sc)   #Se cierra la conexión activa con Spark