# Lista de todos los paquetes que necesitas
paquetes <- c(
"tidyverse", "lubridate", "janitor", "ggplot2", "plotly",
"highcharter", "echarts4r", "leaflet", "sf", "skimr"
)
# Instala solo los que no tengas
instalados <- rownames(installed.packages())
for (p in paquetes) {
if (!(p %in% instalados)) {
install.packages(p)
}
}
# Luego los cargas
lapply(paquetes, library, character.only = TRUE)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
##
## Attaching package: 'janitor'
##
##
## The following objects are masked from 'package:stats':
##
## chisq.test, fisher.test
##
##
##
## Attaching package: 'plotly'
##
##
## The following object is masked from 'package:ggplot2':
##
## last_plot
##
##
## The following object is masked from 'package:stats':
##
## filter
##
##
## The following object is masked from 'package:graphics':
##
## layout
##
##
## Registered S3 method overwritten by 'quantmod':
## method from
## as.zoo.data.frame zoo
##
## Linking to GEOS 3.13.0, GDAL 3.8.5, PROJ 9.5.1; sf_use_s2() is TRUE
## [[1]]
## [1] "lubridate" "forcats" "stringr" "dplyr" "purrr" "readr"
## [7] "tidyr" "tibble" "ggplot2" "tidyverse" "stats" "graphics"
## [13] "grDevices" "utils" "datasets" "methods" "base"
##
## [[2]]
## [1] "lubridate" "forcats" "stringr" "dplyr" "purrr" "readr"
## [7] "tidyr" "tibble" "ggplot2" "tidyverse" "stats" "graphics"
## [13] "grDevices" "utils" "datasets" "methods" "base"
##
## [[3]]
## [1] "janitor" "lubridate" "forcats" "stringr" "dplyr" "purrr"
## [7] "readr" "tidyr" "tibble" "ggplot2" "tidyverse" "stats"
## [13] "graphics" "grDevices" "utils" "datasets" "methods" "base"
##
## [[4]]
## [1] "janitor" "lubridate" "forcats" "stringr" "dplyr" "purrr"
## [7] "readr" "tidyr" "tibble" "ggplot2" "tidyverse" "stats"
## [13] "graphics" "grDevices" "utils" "datasets" "methods" "base"
##
## [[5]]
## [1] "plotly" "janitor" "lubridate" "forcats" "stringr" "dplyr"
## [7] "purrr" "readr" "tidyr" "tibble" "ggplot2" "tidyverse"
## [13] "stats" "graphics" "grDevices" "utils" "datasets" "methods"
## [19] "base"
##
## [[6]]
## [1] "highcharter" "plotly" "janitor" "lubridate" "forcats"
## [6] "stringr" "dplyr" "purrr" "readr" "tidyr"
## [11] "tibble" "ggplot2" "tidyverse" "stats" "graphics"
## [16] "grDevices" "utils" "datasets" "methods" "base"
##
## [[7]]
## [1] "echarts4r" "highcharter" "plotly" "janitor" "lubridate"
## [6] "forcats" "stringr" "dplyr" "purrr" "readr"
## [11] "tidyr" "tibble" "ggplot2" "tidyverse" "stats"
## [16] "graphics" "grDevices" "utils" "datasets" "methods"
## [21] "base"
##
## [[8]]
## [1] "leaflet" "echarts4r" "highcharter" "plotly" "janitor"
## [6] "lubridate" "forcats" "stringr" "dplyr" "purrr"
## [11] "readr" "tidyr" "tibble" "ggplot2" "tidyverse"
## [16] "stats" "graphics" "grDevices" "utils" "datasets"
## [21] "methods" "base"
##
## [[9]]
## [1] "sf" "leaflet" "echarts4r" "highcharter" "plotly"
## [6] "janitor" "lubridate" "forcats" "stringr" "dplyr"
## [11] "purrr" "readr" "tidyr" "tibble" "ggplot2"
## [16] "tidyverse" "stats" "graphics" "grDevices" "utils"
## [21] "datasets" "methods" "base"
##
## [[10]]
## [1] "skimr" "sf" "leaflet" "echarts4r" "highcharter"
## [6] "plotly" "janitor" "lubridate" "forcats" "stringr"
## [11] "dplyr" "purrr" "readr" "tidyr" "tibble"
## [16] "ggplot2" "tidyverse" "stats" "graphics" "grDevices"
## [21] "utils" "datasets" "methods" "base"
campañas <- read_csv("marketing_campañas.csv") %>% clean_names()
## Rows: 300 Columns: 3
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): Nombre_Campaña, Departamento
## dbl (1): ID_Campaña
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
str(campañas)
## spc_tbl_ [300 × 3] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id_campana : num [1:300] 1 2 3 4 5 6 7 8 9 10 ...
## $ nombre_campana: chr [1:300] "Campaña_1" "Campaña_2" "Campaña_3" "Campaña_4" ...
## $ departamento : chr [1:300] "La Paz" "Pando" "Oruro" "Tarija" ...
## - attr(*, "spec")=
## .. cols(
## .. ID_Campaña = col_double(),
## .. Nombre_Campaña = col_character(),
## .. Departamento = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
clientes <- read_csv("marketing_clientes.csv") %>% clean_names()
## Rows: 1000 Columns: 6
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (4): Nombre, Genero, Departamento, Ciudad
## dbl (2): ID_Cliente, Edad
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
str(clientes)
## spc_tbl_ [1,000 × 6] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id_cliente : num [1:1000] 1 2 3 4 5 6 7 8 9 10 ...
## $ nombre : chr [1:1000] "Cliente_1" "Cliente_2" "Cliente_3" "Cliente_4" ...
## $ edad : num [1:1000] 56 46 32 60 25 38 56 36 40 28 ...
## $ genero : chr [1:1000] "Masculino" "Otro" "Otro" "Femenino" ...
## $ departamento: chr [1:1000] "Chuquisaca" "Potosí" "Oruro" "Beni" ...
## $ ciudad : chr [1:1000] "Sucre" "Potosí" "Oruro" "Trinidad" ...
## - attr(*, "spec")=
## .. cols(
## .. ID_Cliente = col_double(),
## .. Nombre = col_character(),
## .. Edad = col_double(),
## .. Genero = col_character(),
## .. Departamento = col_character(),
## .. Ciudad = col_character()
## .. )
## - attr(*, "problems")=<externalptr>
servicios <- read_csv("marketing_servicios.csv") %>% clean_names()
## Rows: 200 Columns: 4
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (2): Nombre_Servicio, Categoría
## dbl (2): ID_Servicio, Precio_Unitario
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
str(servicios)
## spc_tbl_ [200 × 4] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id_servicio : num [1:200] 1 2 3 4 5 6 7 8 9 10 ...
## $ nombre_servicio: chr [1:200] "Email Marketing" "Contenido" "Contenido" "Publicidad" ...
## $ categoria : chr [1:200] "Creatividad" "Desarrollo Web" "Análisis de Datos" "Desarrollo Web" ...
## $ precio_unitario: num [1:200] 712 1639 584 1395 1544 ...
## - attr(*, "spec")=
## .. cols(
## .. ID_Servicio = col_double(),
## .. Nombre_Servicio = col_character(),
## .. Categoría = col_character(),
## .. Precio_Unitario = col_double()
## .. )
## - attr(*, "problems")=<externalptr>
transacciones <- read_csv("marketing_transacciones.csv") %>% clean_names()
## Rows: 5000 Columns: 7
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (6): ID_Transaccion, ID_Cliente, ID_Servicio, ID_Campaña, Cantidad, Total
## date (1): Fecha
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
str(transacciones)
## spc_tbl_ [5,000 × 7] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
## $ id_transaccion: num [1:5000] 1 2 3 4 5 6 7 8 9 10 ...
## $ id_cliente : num [1:5000] 450 892 276 888 30 534 814 711 831 777 ...
## $ id_servicio : num [1:5000] 29 156 192 56 78 21 74 97 160 38 ...
## $ id_campana : num [1:5000] 295 125 221 210 295 158 25 15 108 166 ...
## $ cantidad : num [1:5000] 5 2 7 4 5 9 5 4 8 8 ...
## $ total : num [1:5000] 3909 1922 12621 2769 3784 ...
## $ fecha : Date[1:5000], format: "2023-01-11" "2023-07-14" ...
## - attr(*, "spec")=
## .. cols(
## .. ID_Transaccion = col_double(),
## .. ID_Cliente = col_double(),
## .. ID_Servicio = col_double(),
## .. ID_Campaña = col_double(),
## .. Cantidad = col_double(),
## .. Total = col_double(),
## .. Fecha = col_date(format = "")
## .. )
## - attr(*, "problems")=<externalptr>
departamentos_geo <- st_read("bolivia_departamentos_dos.geojson")
## Reading layer `bolivia_departamentos_dos' from data source
## `/Users/oscargauss/Documents/studies/master-in-artificial-intelligence-and-data-science-for-business-transformation/m-3-modelamiento-y-visualización-de-la-información/practica-3/bolivia_departamentos_dos.geojson'
## using driver `GeoJSON'
## Simple feature collection with 9 features and 1 field
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: -68.6193 ymin: -22 xmax: -62.6561 ymax: -10.5
## Geodetic CRS: WGS 84
str(departamentos_geo)
## Classes 'sf' and 'data.frame': 9 obs. of 2 variables:
## $ DEPARTAMEN: chr "La Paz" "Cochabamba" "Santa Cruz" "Oruro" ...
## $ geometry :sfc_POLYGON of length 9; first list element: List of 1
## ..$ : num [1:5, 1:2] -68.6 -68.6 -67.6 -67.6 -68.6 ...
## ..- attr(*, "class")= chr [1:3] "XY" "POLYGON" "sfg"
## - attr(*, "sf_column")= chr "geometry"
## - attr(*, "agr")= Factor w/ 3 levels "constant","aggregate",..: NA
## ..- attr(*, "names")= chr "DEPARTAMEN"
Unir datos
datos_completos <- transacciones %>%
left_join(clientes, by = "id_cliente") %>%
left_join(servicios, by = "id_servicio") %>%
left_join(campañas, by = "id_campana")
datos_completos
# Ver campos faltantes
skimr::skim(datos_completos)
| Name | datos_completos |
| Number of rows | 5000 |
| Number of columns | 17 |
| _______________________ | |
| Column type frequency: | |
| character | 8 |
| Date | 1 |
| numeric | 8 |
| ________________________ | |
| Group variables | None |
Variable type: character
| skim_variable | n_missing | complete_rate | min | max | empty | n_unique | whitespace |
|---|---|---|---|---|---|---|---|
| nombre | 0 | 1 | 9 | 12 | 0 | 995 | 0 |
| genero | 0 | 1 | 4 | 9 | 0 | 3 | 0 |
| departamento.x | 0 | 1 | 4 | 10 | 0 | 9 | 0 |
| ciudad | 0 | 1 | 5 | 11 | 0 | 14 | 0 |
| nombre_servicio | 0 | 1 | 3 | 15 | 0 | 5 | 0 |
| categoria | 0 | 1 | 11 | 17 | 0 | 4 | 0 |
| nombre_campana | 0 | 1 | 9 | 11 | 0 | 300 | 0 |
| departamento.y | 0 | 1 | 4 | 10 | 0 | 9 | 0 |
Variable type: Date
| skim_variable | n_missing | complete_rate | min | max | median | n_unique |
|---|---|---|---|---|---|---|
| fecha | 0 | 1 | 2023-01-01 | 2023-12-31 | 2023-07-01 | 365 |
Variable type: numeric
| skim_variable | n_missing | complete_rate | mean | sd | p0 | p25 | p50 | p75 | p100 | hist |
|---|---|---|---|---|---|---|---|---|---|---|
| id_transaccion | 0 | 1 | 2500.50 | 1443.52 | 1.0 | 1250.75 | 2500.50 | 3750.25 | 5000.00 | ▇▇▇▇▇ |
| id_cliente | 0 | 1 | 500.81 | 286.10 | 1.0 | 257.75 | 505.00 | 747.00 | 1000.00 | ▇▇▇▇▇ |
| id_servicio | 0 | 1 | 102.06 | 58.16 | 1.0 | 52.00 | 101.00 | 154.00 | 200.00 | ▇▇▇▇▇ |
| id_campana | 0 | 1 | 152.17 | 86.36 | 1.0 | 78.00 | 153.00 | 228.00 | 300.00 | ▇▇▇▇▇ |
| cantidad | 0 | 1 | 5.00 | 2.59 | 1.0 | 3.00 | 5.00 | 7.00 | 9.00 | ▇▇▃▇▇ |
| total | 0 | 1 | 5176.77 | 4024.42 | 108.8 | 1849.24 | 3957.19 | 7610.85 | 17946.54 | ▇▅▃▂▁ |
| edad | 0 | 1 | 41.01 | 13.49 | 18.0 | 29.00 | 41.00 | 52.00 | 64.00 | ▇▇▇▇▇ |
| precio_unitario | 0 | 1 | 1039.04 | 541.45 | 108.8 | 535.58 | 996.93 | 1508.13 | 1994.06 | ▇▇▇▆▇ |
# Ver tipos de datos y fechas
glimpse(datos_completos)
## Rows: 5,000
## Columns: 17
## $ id_transaccion <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,…
## $ id_cliente <dbl> 450, 892, 276, 888, 30, 534, 814, 711, 831, 777, 680, …
## $ id_servicio <dbl> 29, 156, 192, 56, 78, 21, 74, 97, 160, 38, 142, 125, 1…
## $ id_campana <dbl> 295, 125, 221, 210, 295, 158, 25, 15, 108, 166, 254, 2…
## $ cantidad <dbl> 5, 2, 7, 4, 5, 9, 5, 4, 8, 8, 7, 1, 1, 9, 2, 9, 9, 6, …
## $ total <dbl> 3908.90, 1922.50, 12621.28, 2769.08, 3784.10, 3290.13,…
## $ fecha <date> 2023-01-11, 2023-07-14, 2023-04-29, 2023-09-18, 2023-…
## $ nombre <chr> "Cliente_450", "Cliente_892", "Cliente_276", "Cliente_…
## $ edad <dbl> 39, 62, 20, 40, 44, 53, 22, 23, 21, 47, 28, 29, 51, 34…
## $ genero <chr> "Femenino", "Femenino", "Otro", "Femenino", "Masculino…
## $ departamento.x <chr> "La Paz", "La Paz", "Pando", "Chuquisaca", "Oruro", "T…
## $ ciudad <chr> "La Paz", "El Alto", "Cobija", "Sucre", "Oruro", "Yacu…
## $ nombre_servicio <chr> "Redes Sociales", "SEO", "Contenido", "SEO", "Redes So…
## $ categoria <chr> "Creatividad", "Desarrollo Web", "Creatividad", "Desar…
## $ precio_unitario <dbl> 781.78, 961.25, 1803.04, 692.27, 756.82, 365.57, 1318.…
## $ nombre_campana <chr> "Campaña_295", "Campaña_125", "Campaña_221", "Campaña_…
## $ departamento.y <chr> "Tarija", "Cochabamba", "Beni", "Tarija", "Tarija", "B…
# Convertir fechas si es necesario
datos_completos <- datos_completos %>%
mutate(fecha_transaccion = ymd(fecha))
unique(datos_completos$departamento.x)
## [1] "La Paz" "Pando" "Chuquisaca" "Oruro" "Tarija"
## [6] "Beni" "Santa Cruz" "Cochabamba" "Potosí"
unique(departamentos_geo$DEPARTAMEN)
## [1] "La Paz" "Cochabamba" "Santa Cruz" "Oruro" "Potosí"
## [6] "Chuquisaca" "Tarija" "Beni" "Pando"
Crear entre 6 y 8 gráficos interactivos. Algunos ejemplos sugeridos:
# Librerías necesarias
library(tidyverse)
library(plotly)
# Unir y procesar
ventas_por_categoria <- transacciones %>%
left_join(servicios, by = "id_servicio") %>%
group_by(categoria) %>%
summarise(total_ventas = sum(total, na.rm = TRUE)) %>%
arrange(desc(total_ventas))
# Graficar
plot_ly(
data = ventas_por_categoria,
x = ~categoria,
y = ~total_ventas,
type = "bar",
text = ~paste("Bs.", total_ventas),
marker = list(color = "steelblue")
) %>%
layout(
title = "Ventas por Categoría de Servicio",
xaxis = list(title = "Categoría de Servicio"),
yaxis = list(title = "Total de Ventas (Bs.)")
)
# Librerías necesarias
library(tidyverse)
library(plotly)
# Crear rangos de edad
clientes <- clientes %>%
mutate(
rango_edad = cut(
edad,
breaks = c(0, 18, 25, 35, 45, 55, 65, 100),
labels = c("0-18", "19-25", "26-35", "36-45", "46-55", "56-65", "66+"),
right = FALSE
)
)
# Contar clientes por rango
distribucion_edad <- clientes %>%
count(rango_edad) %>%
arrange(rango_edad)
# Gráfico interactivo
plot_ly(
data = distribucion_edad,
x = ~rango_edad,
y = ~n,
type = "bar",
marker = list(color = 'darkorange'),
text = ~n,
textposition = 'auto'
) %>%
layout(
title = "Distribución de Clientes por Edad",
xaxis = list(title = "Rango de Edad"),
yaxis = list(title = "Cantidad de Clientes")
)
# Librerías necesarias
library(tidyverse)
library(plotly)
# Unir transacciones con clientes para obtener departamento
ventas_por_departamento <- transacciones %>%
rename(id_cliente = id_cliente) %>%
left_join(clientes, by = "id_cliente")
# Agrupar por departamento y sumar total de ventas
ventas_departamento <- ventas_por_departamento %>%
group_by(departamento) %>%
summarise(total_ventas = sum(total, na.rm = TRUE)) %>%
arrange(desc(total_ventas))
# Crear gráfico interactivo
plot_ly(
data = ventas_departamento,
x = ~departamento,
y = ~total_ventas,
type = "bar",
marker = list(color = "steelblue"),
text = ~paste("Bs.", total_ventas),
textposition = "auto"
) %>%
layout(
title = "Ventas por Departamento",
xaxis = list(title = "Departamento"),
yaxis = list(title = "Total de Ventas (Bs.)")
)
# Librerías necesarias
library(tidyverse)
library(plotly)
# Unir transacciones con clientes para obtener el género
ventas_por_genero <- transacciones %>%
left_join(clientes, by = "id_cliente")
# Agrupar por género y sumar total de ventas
ventas_genero <- ventas_por_genero %>%
group_by(genero) %>%
summarise(total_ventas = sum(total, na.rm = TRUE)) %>%
arrange(desc(total_ventas))
# Gráfico interactivo
plot_ly(
data = ventas_genero,
x = ~genero,
y = ~total_ventas,
type = "bar",
text = ~paste("Bs.", total_ventas),
marker = list(color = "mediumseagreen"),
textposition = "auto"
) %>%
layout(
title = "Ventas por Género",
xaxis = list(title = "Género"),
yaxis = list(title = "Total de Ventas (Bs.)")
)
# Librerías necesarias
library(tidyverse)
library(plotly)
# Unir transacciones con clientes para obtener ciudad
participacion_ciudad <- transacciones %>%
left_join(clientes, by = "id_cliente")
# Contar transacciones por ciudad
conteo_ciudad <- participacion_ciudad %>%
group_by(ciudad) %>%
summarise(participacion = n()) %>%
arrange(desc(participacion))
# Crear gráfico interactivo
plot_ly(
data = conteo_ciudad,
x = ~reorder(ciudad, -participacion),
y = ~participacion,
type = "bar",
marker = list(color = "tomato"),
text = ~paste("Transacciones:", participacion),
textposition = "auto"
) %>%
layout(
title = "Participación por Ciudad (número de transacciones)",
xaxis = list(title = "Ciudad", tickangle = -45),
yaxis = list(title = "Cantidad de Transacciones")
)
# Librerías necesarias
library(tidyverse)
library(plotly)
transacciones <- transacciones %>%
mutate(fecha = as.Date(fecha))
# Agrupar por fecha y sumar ventas
ventas_por_fecha <- transacciones %>%
group_by(fecha) %>%
summarise(total_ventas = sum(total, na.rm = TRUE)) %>%
arrange(fecha)
# Crear gráfico de líneas interactivo
plot_ly(
data = ventas_por_fecha,
x = ~fecha,
y = ~total_ventas,
type = 'scatter',
mode = 'lines+markers',
line = list(color = 'royalblue'),
marker = list(size = 5)
) %>%
layout(
title = "Tendencias de Ventas por Fecha",
xaxis = list(title = "Fecha"),
yaxis = list(title = "Total de Ventas (Bs.)")
)
# Librerías necesarias
library(tidyverse)
library(plotly)
# Graficar histograma interactivo con plotly
plot_ly(
data = transacciones,
x = ~total,
type = "histogram",
nbinsx = 30, # número de barras (bins)
marker = list(color = "purple")
) %>%
layout(
title = "Histograma de Frecuencias de Montos por Transacción",
xaxis = list(title = "Monto Total de la Transacción (Bs.)"),
yaxis = list(title = "Frecuencia")
)
# Librerías necesarias
library(tidyverse)
library(plotly)
# Unir transacciones con clientes
datos_dispersion <- transacciones %>%
left_join(clientes, by = "id_cliente")
# Crear gráfico de dispersión
plot_ly(
data = datos_dispersion,
x = ~edad,
y = ~total,
type = 'scatter',
mode = 'markers',
marker = list(size = 7, color = 'rgba(0, 123, 255, 0.6)', line = list(width = 1, color = 'darkblue')),
text = ~paste("Cliente:", nombre, "<br>Género:", genero)
) %>%
layout(
title = "Dispersión entre Edad y Monto de Transacción",
xaxis = list(title = "Edad del Cliente"),
yaxis = list(title = "Monto Total de la Transacción (Bs.)")
)
library(sf)
library(leaflet)
library(dplyr)
library(RColorBrewer)
# Leer el GeoJSON
departamentos_geo <- st_read("bolivia_departamentos_dos.geojson")
## Reading layer `bolivia_departamentos_dos' from data source
## `/Users/oscargauss/Documents/studies/master-in-artificial-intelligence-and-data-science-for-business-transformation/m-3-modelamiento-y-visualización-de-la-información/practica-3/bolivia_departamentos_dos.geojson'
## using driver `GeoJSON'
## Simple feature collection with 9 features and 1 field
## Geometry type: POLYGON
## Dimension: XY
## Bounding box: xmin: -68.6193 ymin: -22 xmax: -62.6561 ymax: -10.5
## Geodetic CRS: WGS 84
# Asegurar sistema de coordenadas compatible con Leaflet
departamentos_geo <- st_transform(departamentos_geo, crs = 4326)
rutas <- list(
Ruta1 = data.frame(
ciudad = c("La Paz", "Oruro", "Potosí", "Tarija"),
lat = c(-16.5, -17.98, -19.58, -21.53),
lng = c(-68.15, -67.12, -65.75, -64.73)
),
Ruta2 = data.frame(
ciudad = c("Santa Cruz", "Cochabamba", "Sucre"),
lat = c(-17.78, -17.39, -19.04),
lng = c(-63.18, -66.15, -65.26)
),
Ruta3 = data.frame(
ciudad = c("Cobija", "Riberalta", "Trinidad"),
lat = c(-11.02, -11.01, -14.83),
lng = c(-68.77, -66.13, -64.90)
),
Ruta4 = data.frame(
ciudad = c("Villazón", "Uyuni", "La Paz"),
lat = c(-22.08, -20.46, -16.5),
lng = c(-65.6, -66.83, -68.15)
)
)
Visualizar cada ruta con distinto color.
Ver información al pasar el mouse (tooltip).
Aplicar un filtro que permita seleccionar qué ruta mostrar.
# Paleta de colores para las rutas
colores <- brewer.pal(4, "Set1")
# Mapa base con departamentos
mapa <- leaflet() %>%
addTiles() %>%
addPolygons(
data = departamentos_geo,
fillColor = "transparent",
color = "gray",
weight = 1,
label = ~DEPARTAMEN
)
# Agregar rutas y marcadores
for (i in seq_along(rutas)) {
nombre_ruta <- names(rutas)[i]
puntos <- rutas[[i]]
coords <- as.matrix(puntos[, c("lng", "lat")])
# Añadir línea de ruta
mapa <- mapa %>%
addPolylines(
lng = coords[,1],
lat = coords[,2],
color = colores[i],
weight = 4,
opacity = 0.8,
group = nombre_ruta,
popup = paste("<b>", nombre_ruta, "</b><br>Ruta: ", paste(puntos$ciudad, collapse = " → "))
) %>%
addCircleMarkers(
lng = puntos$lng,
lat = puntos$lat,
label = puntos$ciudad,
radius = 6,
color = colores[i],
fillOpacity = 0.9,
group = nombre_ruta
)
}
# Añadir control de capas (filtro por ruta)
mapa <- mapa %>%
addLayersControl(
overlayGroups = names(rutas),
options = layersControlOptions(collapsed = FALSE)
)
# Mostrar el mapa
mapa
Mostrar al menos 3 indicadores clave en el dashboard.
# Librerías necesarias
library(shiny)
library(bs4Dash)
##
## Attaching package: 'bs4Dash'
## The following objects are masked from 'package:shiny':
##
## actionButton, column, insertTab, navbarMenu, tabsetPanel
## The following object is masked from 'package:graphics':
##
## box
library(tidyverse)
library(scales)
##
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
##
## discard
## The following object is masked from 'package:readr':
##
## col_factor
total_ingresos <- sum(transacciones$total, na.rm = TRUE)
total_clientes <- n_distinct(transacciones$id_cliente)
total_transacciones <- nrow(transacciones)
servicio_mas_solicitado <- transacciones %>%
count(id_servicio, sort = TRUE) %>%
left_join(servicios, by = "id_servicio") %>%
slice(1) %>%
select(nombre_servicio, n)
ventas_por_departamento <- transacciones %>%
left_join(clientes, by = "id_cliente") %>%
group_by(departamento) %>%
summarise(total_ventas = sum(total, na.rm = TRUE)) %>%
arrange(desc(total_ventas)) %>%
slice(1)
ui <- bs4DashPage(
title = "Dashboard de KPIs",
header = bs4DashNavbar(title = "Indicadores Clave de Marketing"),
sidebar = bs4DashSidebar(
skin = "light",
status = "primary",
bs4SidebarMenu(
bs4SidebarMenuItem("KPIs", tabName = "kpis", icon = icon("chart-line")),
bs4SidebarMenuItem("Créditos", tabName = "creditos", icon = icon("info-circle"))
)
),
body = bs4DashBody(
bs4TabItems(
# TAB KPIs
bs4TabItem(tabName = "kpis",
h2("KPIs del Sistema de Marketing"),
fluidRow(
bs4ValueBox(value = dollar_format(prefix = "Bs. ")(total_ingresos),
subtitle = "Total de Ingresos",
color = "success", icon = icon("dollar-sign"), width = 6),
bs4ValueBox(value = total_clientes,
subtitle = "Clientes Únicos",
color = "info", icon = icon("users"), width = 6)
),
fluidRow(
bs4ValueBox(value = total_transacciones,
subtitle = "Total de Transacciones",
color = "warning", icon = icon("receipt"), width = 6),
bs4ValueBox(value = servicio_mas_solicitado,
subtitle = "Servicio Más Solicitado",
color = "indigo", icon = icon("star"), width = 6)
),
fluidRow(
bs4ValueBox(value = ventas_por_departamento,
subtitle = "Departamento con Más Ventas",
color = "danger", icon = icon("map-marker-alt"), width = 12)
)
),
# TAB CRÉDITOS
bs4TabItem(tabName = "creditos",
h3("Créditos del Proyecto"),
bs4Card(width = 12, solidHeader = TRUE,
HTML("
<div style='font-size: 18px; line-height: 1.6; padding: 20px;'>
<strong>Nombre del Estudiante:</strong> Oscar Gauss Carvajal Yucra<br>
<strong>Carrera:</strong> Informática<br>
<strong>Módulo:</strong> Visualización de Datos<br>
<strong>Universidad:</strong> Universidad Mayor de San Andres<br>
<strong>Docente:</strong> Diego Parraga Menchaca<br>
<strong>Gestión:</strong> 2025 - Primer Semestre
</div>
")
)
)
)
)
)
server <- function(input, output) {}
shinyApp(ui, server)