En la actualidad, el comercio electrónico se ha consolidado como uno de los principales canales de venta para empresas de todos los tamaños, especialmente aquellas dedicadas a nichos específicos del mercado. En este contexto, el análisis de datos históricos de ventas se convierte en una herramienta esencial para comprender el comportamiento de los consumidores, optimizar procesos operativos y mejorar la rentabilidad del negocio.
El presente estudio se basa en el conjunto de datos Online Retail comprende transacciones registradas entre el 1 de diciembre de 2010 y el 9 de diciembre de 2011 en una tienda minorista en línea con sede en el Reino Unido. Esta empresa se dedica a la venta de regalos únicos para distintas ocasiones, y cuenta con una importante base de clientes mayoristas. El análisis de este conjunto de datos busca identificar tendencias y patrones en el comportamiento de los clientes, así como detectar posibles problemáticas que puedan estar afectando el rendimiento del negocio. Con base en estos hallazgos, se pretende proponer soluciones prácticas y generar información útil para la toma de decisiones estratégicas en un entorno digital cada vez más competitivo.
require(sp)
library(readxl)
Online_Retail <- read_excel("C:/Users/gabui/Downloads/Online Retail.xlsx")
head(Online_Retail)
| InvoiceNo | StockCode | Description | Quantity | InvoiceDate | UnitPrice | CustomerID | Country |
|---|---|---|---|---|---|---|---|
| 536365 | 85123A | WHITE HANGING HEART T-LIGHT HOLDER | 6 | 2010-12-01 08:26:00 | 2.55 | 17850 | United Kingdom |
| 536365 | 71053 | WHITE METAL LANTERN | 6 | 2010-12-01 08:26:00 | 3.39 | 17850 | United Kingdom |
| 536365 | 84406B | CREAM CUPID HEARTS COAT HANGER | 8 | 2010-12-01 08:26:00 | 2.75 | 17850 | United Kingdom |
| 536365 | 84029G | KNITTED UNION FLAG HOT WATER BOTTLE | 6 | 2010-12-01 08:26:00 | 3.39 | 17850 | United Kingdom |
| 536365 | 84029E | RED WOOLLY HOTTIE WHITE HEART. | 6 | 2010-12-01 08:26:00 | 3.39 | 17850 | United Kingdom |
| 536365 | 22752 | SET 7 BABUSHKA NESTING BOXES | 2 | 2010-12-01 08:26:00 | 7.65 | 17850 | United Kingdom |
El comportamiento de las ventas en entornos digitales está sujeto a dinámicas complejas influenciadas por factores estacionales, tendencias de mercado y variables externas. En este contexto, surge la necesidad de implementar metodologías analíticas que permitan descomponer y proyectar los patrones de transacciones comerciales con base en datos históricos registrados en plataformas de venta en línea.
Las empresas de comercio electrónico generan grandes volúmenes de datos transaccionales a lo largo del tiempo. Sin embargo, convertir esos datos en información útil para la toma de decisiones requiere herramientas analíticas adecuadas. El problema estadístico que se plantea en este estudio es el análisis y modelado de series de tiempo con el propósito de entender el comportamiento temporal de las ventas diarias o mensuales y prever su evolución futura.
Esto implica enfrentar desafíos como la estacionalidad de las ventas, los picos de demanda, y la identificación de posibles anomalías que puedan impactar la planificación comercial. Resolver este problema permite anticiparse a periodos de alta o baja demanda, optimizar la gestión del inventario y diseñar campañas de marketing más efectivas.
Desarrollar modelos de series de tiempo que permitan predecir el volumen de ventas de una tienda de comercio electrónico con base en los datos históricos de transacciones. A través de estos modelos, se busca identificar tendencias, patrones estacionales y eventos atípicos, con el fin de mejorar la toma de decisiones en áreas clave como la planificación de inventario, gestión de demanda y estrategia comercial. Este enfoque busca proporcionar una ventaja competitiva al anticipar el comportamiento del mercado y mejorar la eficiencia operativa.
El conjunto de datos Online Retail contiene aproximadamente 541,909 registros distribuidos en 8 variables, que corresponden a transacciones realizadas entre diciembre de 2010 y diciembre de 2011 por una tienda minorista en línea con sede en el Reino Unido. Esta tienda se dedica a la venta de productos de regalo únicos, y atiende tanto a clientes individuales como a mayoristas, con una fuerte concentración de ventas en el mercado británico.
Cada fila representa una línea de detalle dentro de una factura, e incluye información relacionada con el producto vendido, la cantidad, el precio, el cliente y la fecha de compra. Las facturas pueden contener varios productos, por lo que hay múltiples registros con el mismo número de factura (InvoiceNo).
# Cargar librerías necesarias
library(readxl)
library(knitr)
# Leer el archivo Excel (usa la ruta correcta)
Retail <- read_excel("C:/Users/gabui/Downloads/Online Retail.xlsx")
# Crear data frame para almacenar resultados
result <- data.frame(Índice = integer(0), Columna = character(0))
# Recorrer nombres de columnas
for (i in seq_along(colnames(Retail))) {
result <- rbind(result, data.frame(Índice = i, Columna = colnames(Retail)[i]))
}
# Mostrar tabla
kable(result,
col.names = c("Índice", "Columna"),
caption = "Tabla de Índices y Nombres de Columnas",
align = c("c", "l"))
| Índice | Columna |
|---|---|
| 1 | InvoiceNo |
| 2 | StockCode |
| 3 | Description |
| 4 | Quantity |
| 5 | InvoiceDate |
| 6 | UnitPrice |
| 7 | CustomerID |
| 8 | Country |
A continuación vamos a analizar cada variable:
InvoiceNo: Es el número de factura. Es un código único asignado a cada transacción. Como se dijo anteriormente las facturas que comienzan con la letra “C” indican que la transacción fue cancelada o devuelta.
StockCode: Es el código del producto. Es un identificador único para cada artículo en el inventario.
Description: Como su nombre lo indica es la descripción del producto. Indica el nombre o detalles del artículo vendido. Algunos valores están vacíos, lo cual puede dificultar el análisis si no se corrige.
Quantity: Es la cantidad de productos comprados (puede ser negativa, lo que indica una devolución).
InvoiceDate: Fecha y hora en que se realizó la transacción. Es útil para el análisis temporal (tendencias diarias, mensuales, estacionales).
UnitPrice: Es el precio unitario del producto, expresado en libras esterlinas
CustomerID: Es el código único asignado a cada cliente. Algunos registros no tienen este valor (clientes no identificados), lo que puede limitar ciertos análisis como segmentación o fidelización.
Country: Es el país del cliente. Ayuda a identificar el origen geográfico de la compra y a segmentar el mercado por región. El Reino Unido es el país predominante.
A continuacion se hace un resumen estadistico de la informacion
summary(Retail)
## InvoiceNo StockCode Description Quantity
## Length:541909 Length:541909 Length:541909 Min. :-80995.00
## Class :character Class :character Class :character 1st Qu.: 1.00
## Mode :character Mode :character Mode :character Median : 3.00
## Mean : 9.55
## 3rd Qu.: 10.00
## Max. : 80995.00
##
## InvoiceDate UnitPrice CustomerID
## Min. :2010-12-01 08:26:00.00 Min. :-11062.06 Min. :12346
## 1st Qu.:2011-03-28 11:34:00.00 1st Qu.: 1.25 1st Qu.:13953
## Median :2011-07-19 17:17:00.00 Median : 2.08 Median :15152
## Mean :2011-07-04 13:34:57.16 Mean : 4.61 Mean :15288
## 3rd Qu.:2011-10-19 11:27:00.00 3rd Qu.: 4.13 3rd Qu.:16791
## Max. :2011-12-09 12:50:00.00 Max. : 38970.00 Max. :18287
## NA's :135080
## Country
## Length:541909
## Class :character
## Mode :character
##
##
##
##
se pueden observar que antes de aplicar cualquier modelo de series temporales, es imprescindible realizar un proceso de depuración de datos, ya que el conjunto presenta diversos problemas de calidad. Entre los más relevantes se encuentran las facturas canceladas, fácilmente reconocibles porque su número comienza con la letra “C”; los valores negativos en la columna de cantidad, que reflejan devoluciones de productos y deben tratarse adecuadamente para evitar distorsiones en el análisis; los valores faltantes en el identificador del cliente, que dificultan la desagregación de patrones individuales de compra; y los precios unitarios iguales a cero, que pueden indicar errores de registro o promociones mal documentadas. Adicionalmente, es necesario construir nuevas variables temporales a partir de la fecha y hora de la transacción, tales como el mes, el día de la semana o la hora del día, que permiten captar comportamientos cíclicos y estacionales más finos.
A continuacion se realizara una limpieza en la cual se desea eliminar las variables customerID que no tienenen clientes(estan en blanco) , tambien eliminar los precios menores a 0, las devoluciones y cancelaciones de los productos. Tambien se desa calcular el monto total y extraer solamente la fecha de compra del producto sin importar la hora.
library(readxl)
library(dplyr)
library(lubridate)
retail <- read_excel("C:/Users/gabui/Downloads/Online Retail.xlsx")
retail_clean <- retail %>%
filter(!is.na(CustomerID),
Quantity > 0,
UnitPrice > 0,
!grepl("^C", InvoiceNo)) %>%
mutate(TotalSales = Quantity * UnitPrice,
InvoiceDate = as.POSIXct(InvoiceDate),
Date = as.Date(InvoiceDate))
glimpse(retail_clean)
## Rows: 397,884
## Columns: 10
## $ InvoiceNo <chr> "536365", "536365", "536365", "536365", "536365", "536365"…
## $ StockCode <chr> "85123A", "71053", "84406B", "84029G", "84029E", "22752", …
## $ Description <chr> "WHITE HANGING HEART T-LIGHT HOLDER", "WHITE METAL LANTERN…
## $ Quantity <dbl> 6, 6, 8, 6, 6, 2, 6, 6, 6, 32, 6, 6, 8, 6, 6, 3, 2, 3, 3, …
## $ InvoiceDate <dttm> 2010-12-01 08:26:00, 2010-12-01 08:26:00, 2010-12-01 08:2…
## $ UnitPrice <dbl> 2.55, 3.39, 2.75, 3.39, 3.39, 7.65, 4.25, 1.85, 1.85, 1.69…
## $ CustomerID <dbl> 17850, 17850, 17850, 17850, 17850, 17850, 17850, 17850, 17…
## $ Country <chr> "United Kingdom", "United Kingdom", "United Kingdom", "Uni…
## $ TotalSales <dbl> 15.30, 20.34, 22.00, 20.34, 20.34, 15.30, 25.50, 11.10, 11…
## $ Date <date> 2010-12-01, 2010-12-01, 2010-12-01, 2010-12-01, 2010-12-0…
summary(retail_clean)
## InvoiceNo StockCode Description Quantity
## Length:397884 Length:397884 Length:397884 Min. : 1.00
## Class :character Class :character Class :character 1st Qu.: 2.00
## Mode :character Mode :character Mode :character Median : 6.00
## Mean : 12.99
## 3rd Qu.: 12.00
## Max. :80995.00
## InvoiceDate UnitPrice CustomerID
## Min. :2010-12-01 08:26:00.00 Min. : 0.001 Min. :12346
## 1st Qu.:2011-04-07 11:12:00.00 1st Qu.: 1.250 1st Qu.:13969
## Median :2011-07-31 14:39:00.00 Median : 1.950 Median :15159
## Mean :2011-07-10 23:41:23.50 Mean : 3.116 Mean :15294
## 3rd Qu.:2011-10-20 14:33:00.00 3rd Qu.: 3.750 3rd Qu.:16795
## Max. :2011-12-09 12:50:00.00 Max. :8142.750 Max. :18287
## Country TotalSales Date
## Length:397884 Min. : 0.00 Min. :2010-12-01
## Class :character 1st Qu.: 4.68 1st Qu.:2011-04-07
## Mode :character Median : 11.80 Median :2011-07-31
## Mean : 22.40 Mean :2011-07-10
## 3rd Qu.: 19.80 3rd Qu.:2011-10-20
## Max. :168469.60 Max. :2011-12-09
dim(retail_clean)
## [1] 397884 10
library(ggplot2)
library(dplyr)
library(patchwork)
# Ventas diarias agregadas
ventas_diarias <- retail_clean %>%
group_by(Date) %>%
summarise(VentasDiarias = sum(TotalSales)) %>%
ungroup() %>%
mutate(Year = year(Date),
Day = day(Date),
Month = month(Date, label = TRUE))
# Filtrar por año
ventas_2010 <- ventas_diarias %>% filter(Year == 2010)
ventas_2011 <- ventas_diarias %>% filter(Year == 2011)
grafico_2010 <- ggplot(ventas_2010, aes(x = Date, y = VentasDiarias)) +
geom_line(color = "steelblue") +
labs(title = "Ventas Diarias - 2010", x = "Fecha", y = "Ventas (£)") +
theme_minimal()
# Gráfico para 2011
grafico_2011 <- ggplot(ventas_2011, aes(x = Date, y = VentasDiarias)) +
geom_line(color = "darkgreen") +
labs(title = "Ventas Diarias - 2011", x = "Fecha", y = "Ventas (£)") +
theme_minimal()
# Mostrar ambos gráficos uno al lado del otro
grafico_2010 + grafico_2011
Ventas Diarias - 2010
El gráfico de 2010 muestra una serie corta, correspondiente únicamente al mes de diciembre, lo cual es coherente con el hecho de que los datos inician a mediados de ese mes. En ese período, las ventas presentan una alta volatilidad con varios picos que alcanzan los £50,000. Este comportamiento sugiere una posible estacionalidad de fin de año, donde la demanda puede haberse incrementado por compras navideñas. Sin embargo, hacia los últimos días del mes se evidencia una caída abrupta en las ventas, lo cual puede deberse al cierre de operaciones durante días festivos o a una disminución en la actividad comercial tras la temporada alta.
En contraste, el gráfico de 2011 muestra una serie completa de todo el año, lo que permite observar un comportamiento más amplio y estructurado. Se destacan varias características importantes:
Tendencia creciente: A lo largo del año se aprecia un aumento progresivo en las ventas, especialmente a partir del segundo semestre. Esto podría indicar una expansión del negocio, una mejora en la estrategia comercial o el efecto acumulado de la fidelización de clientes.
Alta variabilidad: Hay muchos picos de ventas, algunos muy pronunciados (superando £100,000), intercalados con caídas. Esta variabilidad diaria puede explicarse por promociones especiales, eventos, días festivos o concentraciones de pedidos.
Pico extremo en diciembre: Al igual que en 2010, diciembre vuelve a mostrar un aumento fuerte en las ventas, confirmando una posible estacionalidad de fin de año. El pico más alto del gráfico ocurre en este mes, lo que refuerza la hipótesis de que la tienda obtiene una parte significativa de sus ingresos en esta temporada.
Ahora analizamos las ventas por pais:
library(dplyr)
# Agrupar por país y calcular ventas totales
ventas_por_pais <- retail_clean %>%
group_by(Country) %>%
summarise(VentasTotales = sum(TotalSales)) %>%
arrange(desc(VentasTotales))
top_paises <- ventas_por_pais %>% slice_max(VentasTotales, n = 10)
ggplot(top_paises, aes(x = reorder(Country, VentasTotales), y = VentasTotales)) +
geom_bar(stat = "identity", fill = "darkorange") +
coord_flip() +
labs(title = "Top 10 Países por Ventas Totales",
x = "País",
y = "Ventas Totales (£)") +
theme_minimal()
El gráfico de barras presentado muestra claramente que el Reino Unido representa, por un amplio margen, el país con mayores ventas totales en la base de datos analizada. Su participación es considerablemente superior a la del resto de países, lo que sugiere que la mayoría de las transacciones comerciales se concentran allí. Esta situación podría explicarse por la posible ubicación de la empresa en el Reino Unido, lo cual facilita la logística, reduce los costos operativos y mejora la eficiencia del servicio local. En contraste, países como los Países Bajos, Irlanda (EIRE), Alemania, Francia y Australia presentan ventas significativamente menores, lo que revela una alta concentración del mercado en una sola región. Esta disparidad también sugiere una oportunidad de expansión en mercados europeos desarrollados donde la empresa aún no ha alcanzado un nivel alto de penetración. Por otro lado, países como Bélgica y Suecia reflejan ventas casi marginales, lo que podría deberse a barreras logísticas, culturales o a una menor presencia de marca. En conjunto, este análisis señala la necesidad de evaluar estrategias de diversificación geográfica, desarrollar campañas enfocadas en mercados con bajo volumen y profundizar en estudios que identifiquen factores que limitan el crecimiento en otros países.
Observemos la estacionalidad de los paises más importantes:
library(dplyr)
library(ggplot2)
library(lubridate)
# Crear columna Month a partir de InvoiceDate (primer día de cada mes)
retail_clean <- retail_clean %>%
mutate(Month = floor_date(InvoiceDate, "month"),
TotalSales = Quantity * UnitPrice)
# Calcular ventas mensuales por país
ventas_mensuales <- retail_clean %>%
group_by(Country, Month) %>%
summarise(VentasTotales = sum(TotalSales, na.rm = TRUE), .groups = "drop")
# Identificar los 6 países con mayores ventas totales
top_paises <- retail_clean %>%
group_by(Country) %>%
summarise(VentasTotales = sum(TotalSales, na.rm = TRUE), .groups = "drop") %>%
top_n(6, VentasTotales) %>%
pull(Country)
# Filtrar ventas mensuales solo para esos 6 países
ventas_top <- ventas_mensuales %>%
filter(Country %in% top_paises)
# Graficar la estacionalidad de ventas por país
ggplot(ventas_top, aes(x = Month, y = VentasTotales, color = Country)) +
geom_line(size = 1) +
labs(title = "Estacionalidad de Ventas por País",
x = "Mes",
y = "Ventas Totales",
color = "País") +
theme_minimal()
El gráfico muestra la estacionalidad de las ventas mensuales desglosadas por país, destacando claramente el predominio del Reino Unido (línea fucsia) en comparación con los demás países. Se observa que las ventas en el Reino Unido aumentan significativamente en la segunda mitad del año, alcanzando un máximo entre los meses 10 y 12, lo que sugiere un fuerte efecto estacional posiblemente relacionado con la temporada navideña. En contraste, países como Australia, EIRE, Francia, Alemania y los Países Bajos presentan volúmenes de ventas mucho menores y relativamente estables a lo largo del año, sin picos pronunciados. Esto indica que la dinámica de ventas en esos países no está tan influenciada por la estacionalidad como en el Reino Unido. La diferencia en escala entre los países resalta la concentración del mercado en el Reino Unido, lo cual es crucial al analizar patrones temporales o tomar decisiones estratégicas.
El análisis de series temporales aplicado al conjunto de datos Online Retail permitió comprender de manera integral el comportamiento de las ventas en un entorno de comercio electrónico. En primer lugar, se identificó una clara estacionalidad anual, con un incremento significativo de las ventas en los últimos meses del año, especialmente en diciembre. Esta tendencia confirma la existencia de una temporada alta asociada a las compras navideñas, lo cual representa una oportunidad clave para la planificación estratégica y operativa del negocio.
La depuración de datos fue un paso fundamental para garantizar la calidad del análisis, eliminando transacciones anuladas, precios inconsistentes y registros incompletos. Este proceso permitió construir una base confiable para el cálculo de métricas agregadas, como ventas diarias y ventas por país, y sentó las bases para futuros modelos predictivos de demanda.
Asimismo, el Reino Unido fue identificado como el mercado dominante, con una participación abrumadora en el total de ventas. Esta concentración geográfica plantea un riesgo potencial si no se diversifican los canales de ingreso. Al mismo tiempo, otros países europeos presentan niveles de ventas bajos pero estables, lo cual indica que existe espacio para expansión comercial internacional, siempre que se aborden barreras logísticas o de posicionamiento.
Por último, el análisis por país evidenció diferencias sustanciales en el comportamiento estacional. Mientras que el Reino Unido mostró una variación significativa durante el año, otros países mantuvieron patrones más planos, lo que podría aprovecharse para diseñar campañas de marketing adaptadas a los ciclos de compra de cada región.
En conjunto, estos hallazgos confirman que el uso de herramientas estadísticas sobre series de tiempo no solo facilita la comprensión del comportamiento histórico de las ventas, sino que también proporciona insumos valiosos para anticiparse a la demanda, optimizar recursos y fortalecer la toma de decisiones en un entorno digital competitivo.