Objetivo 1 y 2: Creación de índices

El objetivo de este apartado consiste en clasificar los países en función de su rendimiento en diversas áreas de interés, con el fin de evaluar la relación que dicho desempeño puede tener con el costo de vida en cada país. Específicamente, se utilizarán las variables recopiladas y descritas para definir índices relacionados con la economía, el consumo energético, el bienestar y el gasto público. La elección de estos campos se justifica por su relevancia y las cuestiones que generan, las cuales se detallan en la memoria del estudio.

Antes de adentrarnos en las especificaciones técnicas que se han seguido para cumplir con el objetivo, es importante definir una linea de acción que guiará el desenlace de esta parte de la investigación:

  1. Carga y tratamiento de datos
  2. Normalización de las distribuciones
  3. Definición de los modelos de puntuación y creación de los índices
  4. Discretización por niveles de desempeño
  5. Representación mapas
  6. Construcción de rankings

Librerías

library(tidyverse)
library(readxl)
library(class)
library(dplyr)
library(maps)
library(ggplot2)
library(stringr)
library(leaflet)
library(jsonlite)
library(ggwordcloud)
library(echarts4r.maps)
library(echarts4r)
library(flextable)

1. Carga y tratamiento de datos

Comenzaremos con la carga de la base de datos, previamente limpiada e integrada en el análisis exploratorio.

load("C:\\Users\\fanny\\Downloads\\basedatos2019_completa.RData")
datos = basedatos


# Eliminamos carácteres especiales y signos de puntuación incluidos en los nombres de las variables

nombres_nuevos <- datos %>%
  names() %>%
  gsub("\\.", "_", .)

datos <- datos %>%
  rename_all(~nombres_nuevos)

nombres_nuevos <- datos %>%
  names() %>%
  iconv(to = "ASCII//TRANSLIT")

datos <- datos %>%
  setNames(nombres_nuevos)

Incluimos una serie de variables para enriquecer la calidad de los indicadores métricos que definirán el desempeño en las categorias establecidad. Entre ellas destacamos: el indice de calidad de vida, el indice de sanidad, indice de poder adquisitivo, el indice de contaminación y el indice de clima. Puede consultarse la fuente y la naturaleza de las variables en el HITO1 modificado.

calidad_vida = read_excel("C:\\Users\\fanny\\OneDrive\\Documents\\CIENCIA DE DATOS\\SEGUNDO\\PROYECTO\\Calidad de vida.xlsx")

# Eliminamos carácteres especiales y signos de puntuación incluidos en los nombres de las variables

nombres_nuevos <- calidad_vida %>%
  names() %>%
  gsub(" ", "_", .)

calidad_vida <- calidad_vida %>%
  rename_all(~nombres_nuevos)

nombres_nuevos <- calidad_vida %>%
  names() %>%
  iconv(to = "ASCII//TRANSLIT")

calidad_vida <- calidad_vida %>%
  setNames(nombres_nuevos)


calidad_vida[69, 2] <- 'Hong Kong'
calidad_vida[36, 2] <- 'Taiwán'

# Descartamos el conjunto de variables que no interesa para el estudio 

calidad_vida <- calidad_vida[, !(names(calidad_vida) %in% c("Puesto", "Indice_de_Seguridad", "Indice_de_Costo_de_Vida", "Relacion_Precio/Ingresos_para_Propiedades", "Indice_de_Tiempo_de_Desplazamiento_en_Trafico"))]


# Combinación derecha (incluye todas las filas de datos y las filas coincidentes de calidad_vida)
datos <- merge(calidad_vida, datos, by = "Pais", all.y = TRUE)

Durante el preprocesamiento de los datos, se realizó un tratamiento exhaustivo de los datos faltantes hasta lograr un porcentaje considerado aceptable. No obstante, al desarrollar este objetivo, específicamente en la creación de índices representativos de las categorías, se requiere realizar cálculos sobre registros que no admiten la presencia de datos faltantes. Por lo tanto, es necesario explorar técnicas de imputación y determinar cuál es la más adecuada según las características estructurales de nuestra base de datos.

Analicemos la distribución de faltantes:

#Contar el total de NAs en la base de datos
sum(is.na(datos))
## [1] 498
#Saber el número de NAs por columna
colSums(is.na(datos))
##                                 Pais            Indice_de_Calidad_de_Vida 
##                                    0                                   35 
##          Indice_de_Poder_Adquisitivo                    Indice_de_Sanidad 
##                                   35                                   35 
##              Indice_de_Contaminacion                      Indice_de_Clima 
##                                   35                                   35 
##              Indice_de_Costo_de_Vida                   Indice_de_Alquiler 
##                                    0                                    0 
## Indice_de_Costo_de_Vida_mas_Alquiler                Indice_de_Comestibles 
##                                    0                                    0 
##    Indice_de_Precios_en_Restaurantes    Indice_de_Poder_Adquisitivo_Local 
##                                    0                                    0 
##                        Salario_Medio                       Salario_Minimo 
##                                   21                                   85 
##                     Indice_Felicidad                        Gasto_Publico 
##                                   14                                   10 
##                      Gasto_Educacion                          Gasto_Salud 
##                                   13                                   11 
##                        Gasto_Defensa               Indice_de_Criminalidad 
##                                   12                                    9 
##                  Indice_de_Seguridad                          Consumo_GWh 
##                                    9                                    9 
##                       CO2_per_capita                     Reserva_Petroleo 
##                                   11                                   51 
##                  Produccion_Petroleo                                  PIB 
##                                   50                                    9 
##                            Poblacion 
##                                    9

Considerando los resultados anteriores, se plantea la posibilidad de excluir del análisis, al menos para el logro de este objetivo, variables como el salario mínimo y aquellas relacionadas con la industria petrolera debido a su alta cantidad de datos faltantes. La imputación de estas variables sería altamente compleja y generaría resultados pocos confiables, ya que la mayoría de los datos resultantes serían sintéticos en lugar de reales. La decisión de suprimir estas variables se tomará más adelante tras explorar la naturaleza de faltantes en las filas.

Antes de descartar atributos, veamos si es posible reducir la porción de faltantes eliminando aquellos países en los que se concentre un alto número:

# Contar los valores faltantes por fila
num_datos_faltantes <- rowSums(is.na(datos[, -1])) # Excluye la columna "Pais"
# Crear la tabla con los nombres de los países y los conteos de datos faltantes
tabla_faltantes <- data.frame(Pais = datos$Pais, Datos_Faltantes = num_datos_faltantes)
tabla_faltantes %>%
  flextable() %>%
  fix_border_issues(part = "all") %>%
  bold(part = "header") %>%
  align(align = "center", part = "all")%>%
  bg(bg = "#A8F6F2", part = "body")%>%
  bg(bg = "#3EEAE2", part = "header")

Pais

Datos_Faltantes

Albania

6

Alemania

0

Arabia Saudita

1

Argelia

6

Argentina

1

Armenia

8

Australia

0

Austria

1

Azerbaiyán

1

Bahamas

13

Bangladés

3

Baréin

8

Bélgica

2

Belice

10

Bielorrusia

1

Birmania

19

Bolivia

6

Bosnia y Herzegovina

4

Brasil

0

Bulgaria

0

Camboya

9

Canadá

0

Catar

3

Chile

0

China

1

Chipre

3

Chipre

3

Colombia

0

Corea del Sur

2

Costa Rica

7

Croacia

0

Cuba

14

Dinamarca

1

Ecuador

1

Egipto

1

El Salvador

9

Emiratos Árabes Unidos

1

Eslovaquia

0

Eslovenia

1

España

0

Estados Unidos

0

Estonia

2

Filipinas

1

Finlandia

3

Fiyi

12

Francia

0

Georgia

1

Ghana

6

Grecia

0

Guatemala

6

Honduras

9

Hong Kong

6

Hungría

0

India

1

Indonesia

1

Irak

7

Irán

1

Irlanda

2

Islandia

3

Israel

0

Italia

1

Jamaica

8

Japón

0

Jordania

1

Kazajistán

1

Kenia

3

Kosovo

18

Kuwait

1

Letonia

2

Líbano

3

Lituania

0

Luxemburgo

3

Macedonia del Norte

3

Malasia

1

Malta

2

Marruecos

1

Mauricio

8

México

0

Moldavia

8

Montenegro

10

Namibia

9

Nepal

8

Nicaragua

11

Nigeria

1

Noruega

1

Nueva Zelanda

0

Omán

2

Países Bajos

0

Pakistán

1

Palestina

16

Panamá

3

Paraguay

11

Perú

1

Polonia

0

Portugal

2

Puerto Rico

17

Reino Unido

0

República Checa

10

República Dominicana

8

Rumania

13

Rusia

0

Serbia

2

Singapur

3

Sri Lanka

5

Sudáfrica

1

Suecia

2

Suiza

3

Tailandia

1

Taiwán

11

Tanzania

9

Trinidad y Tobago

7

Túnez

8

Turquía

10

Ucrania

1

Uganda

8

Uruguay

3

Uzbekistán

8

Venezuela

1

Vietnam

11

Zimbabue

9

# mean(tabla_faltantes$Datos_Faltantes) # Calculamos la media de faltantes por pais = 2.69
# Se recogen aquellos países con mas de 4 faltantes
paises_altos_faltantes <- tabla_faltantes$Pais[tabla_faltantes$Datos_Faltantes >= 4]
paises_altos_faltantes
##  [1] "Albania"              "Argelia"              "Armenia"             
##  [4] "Bahamas"              "Baréin"               "Belice"              
##  [7] "Birmania"             "Bolivia"              "Bosnia y Herzegovina"
## [10] "Camboya"              "Costa Rica"           "Cuba"                
## [13] "El Salvador"          "Fiyi"                 "Ghana"               
## [16] "Guatemala"            "Honduras"             "Hong Kong"           
## [19] "Irak"                 "Jamaica"              "Kosovo"              
## [22] "Mauricio"             "Moldavia"             "Montenegro"          
## [25] "Namibia"              "Nepal"                "Nicaragua"           
## [28] "Palestina"            "Paraguay"             "Puerto Rico"         
## [31] "República Checa"      "República Dominicana" "Rumania"             
## [34] "Sri Lanka"            "Taiwán"               "Tanzania"            
## [37] "Trinidad y Tobago"    "Túnez"                "Turquía"             
## [40] "Uganda"               "Uzbekistán"           "Vietnam"             
## [43] "Zimbabue"

Se procederá a descartar aquellos países que presenten una alta proporción de valores faltantes, tal como se detalla en el listado anterior.La decisión de descartar estos países se basa en la necesidad de mantener la integridad y la confiabilidad de los datos utilizados en el análisis. Los valores faltantes pueden afectar la precisión de los resultados y generar sesgos en las conclusiones obtenidas. Al excluir los países con una alta proporción de datos faltantes, se busca garantizar la validez y la coherencia de los resultados finales.

datos <- subset(datos, !(datos$Pais %in% paises_altos_faltantes))

Tras esta depuración inicial, volvemos ahora a estudiar la distribución de faltantes en las variables de la base de datos para proceder a su imputación.

#Saber el número de NAs por columna
colSums(is.na(datos))
##                                 Pais            Indice_de_Calidad_de_Vida 
##                                    0                                    0 
##          Indice_de_Poder_Adquisitivo                    Indice_de_Sanidad 
##                                    0                                    0 
##              Indice_de_Contaminacion                      Indice_de_Clima 
##                                    0                                    0 
##              Indice_de_Costo_de_Vida                   Indice_de_Alquiler 
##                                    0                                    0 
## Indice_de_Costo_de_Vida_mas_Alquiler                Indice_de_Comestibles 
##                                    0                                    0 
##    Indice_de_Precios_en_Restaurantes    Indice_de_Poder_Adquisitivo_Local 
##                                    0                                    0 
##                        Salario_Medio                       Salario_Minimo 
##                                    3                                   45 
##                     Indice_Felicidad                        Gasto_Publico 
##                                    3                                    0 
##                      Gasto_Educacion                          Gasto_Salud 
##                                    0                                    0 
##                        Gasto_Defensa               Indice_de_Criminalidad 
##                                    0                                    0 
##                  Indice_de_Seguridad                          Consumo_GWh 
##                                    0                                    0 
##                       CO2_per_capita                     Reserva_Petroleo 
##                                    1                                   21 
##                  Produccion_Petroleo                                  PIB 
##                                   19                                    0 
##                            Poblacion 
##                                    0

Como se observó inicialmente, tanto el salario mínimo como las variables relacionadas con la industria petrolera continúan mostrando una alta proporción de valores faltantes. Por lo tanto, se ha tomado la decisión de excluir tanto la producción como la reserva de petróleo del estudio, ya que no son de particular relevancia para el análisis y no se cuentan con atributos relacionados que permitan realizar una imputación coherente. El salario mínimo, por su parte, puede estimarse a partir de otras métricas económicas como se verá más adelante.

datos <- datos[, !(names(datos) %in% c("Produccion_Petroleo", "Reserva_Petroleo"))]

Comprobemos sobre qué variables hay que realizar la imputación:

variables_con_faltantes <- names(datos)[sapply(datos, function(x) any(is.na(x)))]
variables_con_faltantes
## [1] "Salario_Medio"    "Salario_Minimo"   "Indice_Felicidad" "CO2_per_capita"

Imputación por vecino más cercano (en términos de coste de vida)

Tras evaluar varias técnicas de imputación, como la regresión lineal o la imputación múltiple, hemos tomado la decisión de utilizar el método del vecino más cercano debido a su mayor adecuación a la naturaleza de nuestra base de datos y al objetivo de nuestro estudio.

La elección de la imputación por vecino más cercano se justifica por la idea de identificar los registros, en este caso países, que sean más similares en términos de coste de vida, es decir, aquellos que presenten valores más cercanos en las variables que describen el coste de vida. De esta manera, podremos aproximar el valor faltante en el atributo en cuestión.

# iterar sobre las variables y realizar la imputación por vecino más cercano
for (variable in variables_con_faltantes) {
  
  # seleccionar solo las observaciones completas 
  datos_completos <- datos[complete.cases(datos),]
  
  # seleccionar las variables sobre las que se basará la estimación
  variables_para_imputar <- c("Indice_de_Costo_de_Vida", "Indice_de_Alquiler", "Indice_de_Costo_de_Vida_mas_Alquiler", "Indice_de_Comestibles", "Indice_de_Precios_en_Restaurantes",  "Indice_de_Poder_Adquisitivo_Local")
  
  # seleccionar solo las observaciones con valores faltantes en la variable actual
  datos_faltantes <- datos[is.na(datos[[variable]]), variables_para_imputar]
  
  # realizar la imputación por vecino más cercano
  imputados <- knn(datos_completos[, variables_para_imputar], datos_faltantes, datos_completos[[variable]], k = 5)
  
   # verificar si la variable actual está en las variables que deben estar en el rango de 0 a 1 (son porcentajes)
  
  if (variable %in% c("Gasto_Defensa", "Gasto_Educacion", "Gasto_Salud")) {
    imputados <- pmax(0, pmin(1, imputados))}
  
  # asignar los valores imputados al dataframe original
  
  datos[is.na(datos[[variable]]), variable] <- imputados}

# Se modifica manualmente algunas imputaciones que se han detectado imprecisas

# Salario Medio 
datos[datos$Pais == "Luxemburgo", 13] <- 4018
datos[datos$Pais == "Catar", 13] <- 3885
datos[datos$Pais == "Baréin", 13] <- 2000
datos[datos$Pais == "Bangladés", 13] <- 255
datos[datos$Pais == "Uganda", 13] <- 100
datos[datos$Pais == "Túnez", 13] <- 300

# Indice de felicidad
datos[datos$Pais == "Catar", 15] <- 6.374
datos[datos$Pais == "Baréin", 15] <- 6.15
datos[datos$Pais == "Omán", 15] <- 6.43
datos[datos$Pais == "Bangladés", 15] <- 4.456

datos_imputados <- datos
#Contar el total de NAs en la base de datos y comprobar que es 0
sum(is.na(datos))
## [1] 0

Ahora que disponemos de una base completa, podemos proceder con el cálculo de los índices.

2. Normalización

Antes de adentrarnos en la generación de fórmulas como modelos de puntuación, se ha decidido tipificar las variables para ajustar las escalas y los rangos que toman sus valores y conseguir así reducir los sesgos y evitar que una variable condicione toda la ponderación de las categorías

# Partimos por convertir a numeric las variables que no están bien asignadas el tipo de datos

# Crear un vector con los nombres de las variables a convertir
variables <- c("Indice_de_Calidad_de_Vida", "Indice_de_Poder_Adquisitivo", "Indice_de_Sanidad", "Indice_de_Contaminacion", "Indice_de_Clima")

# Iterar sobre las variables y convertirlas a tipo numérico
for (variable in variables) {
  datos[[variable]] <- as.numeric(datos[[variable]])
}

Análisis de distribuciones: histogramas

Generamos un gráfico utilizando los datos obtenidos en el paso anterior, con el propósito de analizar si sus distribuciones se ajustan a un modelo normal.

# Excluir la columna "Pais" y aquellas referidas al coste de vida del dataframe
columnas_excluidas <- c("Pais", "Indice_de_Costo_de_Vida", "Indice_de_Alquiler", "Indice_de_Costo_de_Vida_mas_Alquiler", "Indice_de_Comestibles", "Indice_de_Precios_en_Restaurantes", "Indice_de_Poder_Adquisitivo_Local", "Poblacion")
columnas <- setdiff(colnames(datos), columnas_excluidas)

# Iterar a través de cada columna del dataframe 
for (columna in columnas) {
  # Crear el histograma de la columna actual
  hist(datos[[columna]], main = columna, xlab = columna)
}

Corrección de asimetrías

Tras estudiar el comportamiento de las variables a partir de la representación de sus histogramas, es posible detectar asimetrías derechas e izquierdas y por lo que es conveniente corregirlas mediante transformaciones logarítmicas y cuadráticas respectivamente.

Transformación realizada Variables (x)
\(\log(x)\) Indice Felicidad, Gasto Publico, Gasto Educación, Indice Criminalidad, ConsumoGWh, CO2 per capita, PIB
\(x^2\) Indice de Calidad de Vida, Indice de Sanidad, Indice de Clima, Indice de Seguirdad
datos_normalizados1 <- datos

# Transformaciones logarítmicas


datos_normalizados1$Gasto_Educacion <- log(datos_normalizados1$Gasto_Educacion)
datos_normalizados1$Gasto_Publico <- log(datos_normalizados1$Gasto_Publico)
datos_normalizados1$Gasto_Defensa <- ifelse(datos_normalizados1$Gasto_Defensa != 0, log(datos_normalizados1$Gasto_Defensa), datos_normalizados1$Gasto_Defensa)
datos_normalizados1$Indice_de_Criminalidad <- log(datos_normalizados1$Indice_de_Criminalidad)
datos_normalizados1$Consumo_GWh <- log(datos_normalizados1$Consumo_GWh)
datos_normalizados1$CO2_per_capita <- log(datos_normalizados1$CO2_per_capita) 
datos_normalizados1$PIB <- log(datos_normalizados1$PIB) 
datos_normalizados1$Salario_Medio <- log(datos_normalizados1$Salario_Medio)



# Transformaciones cuadráticas

datos_normalizados1$Indice_de_Calidad_de_Vida <- (datos_normalizados1$Indice_de_Calidad_de_Vida)^2
datos_normalizados1$Indice_de_Sanidad <- (datos_normalizados1$Indice_de_Sanidad)^2
datos_normalizados1$Indice_de_Clima <- (datos_normalizados1$Indice_de_Clima)^2
datos_normalizados1$Indice_de_Seguridad <- (datos_normalizados1$Indice_de_Seguridad)^2

Contrastemos el histograma de la distribución de las variables antes y después de la aplicaación de las transformaciones:

# Excluir las columnas que no interesasn del dataframe

columnas_excluidas <- c("Pais", "Indice_de_Costo_de_Vida", "Indice_de_Alquiler", "Indice_de_Costo_de_Vida_mas_Alquiler", "Indice_de_Comestibles", "Indice_de_Precios_en_Restaurantes",  "Indice_de_Poder_Adquisitivo_Local", "Poblacion")
columnas1 <- setdiff(colnames(datos_normalizados1), columnas_excluidas)

for (columna in columnas1) {
  hist(datos[[columna]], main = paste0(columna, " ORIGINAL"), col = "#ff004e", xlab = columna)
  hist(datos_normalizados1[[columna]], main = paste(columna, " NORMALIZADA"), col = "#1be7dc", xlab = columna)
}

Como se puede comprobar, se han corregido las asimetrías y se ha logrado una distribución de todas las variables que se ajusta al modelo normal. Esto se evidencia en los histogramas, los cuales muestran una forma similar a la curva de una Campana de Gauss.

Ahora que es factible ajustar las distribuciones de las variables utilizando modelos similares, se plantea la necesidad de estandarizarlas. El propósito principal de esta estandarización radica en igualar las escalas, evitando así que los atributos con rangos más amplios ejerzan un dominio desproporcionado en la métrica de distancia. Con el fin de llevar a cabo esta tarea de manera automatizada, se ha definido una fórmula que realiza las operaciones requeridas, es decir, substrae la media y divide entre la desviación estándar. Dicha fórmula se ha aplicado de manera sistemática a todas las variables numéricas presentes en la base de datos.

datos = datos_normalizados1

# Función para tipificar una columna
tipificar_columna <- function(columna) {
  columna <- (columna - mean(columna)) / sd(columna)  # Aplicar la tipificación (estandarización)
  return(columna)
}

# Tipificar todas las variables excepto la primera
datos[, 2:ncol(datos)] <- apply(datos[, 2:ncol(datos)], 2, tipificar_columna)

3. Definición de los modelos de puntuación y creación de los índices

En este apartado trabajaremos para combinar variables en una sola medida o índice con el objetivo de resumir información relevante de interés. En detalle, lo que se busca es definir un instrumento de medición compuesto por un conjunto de variables representativas de un atributo de interés. Dichas variables han sido seleccionadas cuidadosamente y ponderadas de manera sistemática con el fin de reflejar con precisión la dimensión que se busca medir. La idea es que la puntuación resultante proporcione una medida cuantitativa del rendimiento global de la categoría en función de las variables de entrada.

Nos centramos incialmente en la categoría gasto público (al ser el ínidice más complejo al no admitir simples ponderaciones). Queremos conseguir reflejar tanto la magnitud como la distribución del gasto con el fin de poder identificar la porción que representa el presupuesto con respecto a la riqueza total del país, las prioridades otorgadas a cada sector de responsabilidad pública y poder obtener una imagen más precisa de cómo se están utilizando y asignando los recursos disponibles para satisfacer las necesidades y demandas de la sociedad en áreas críticas.

Para la construcción de este índice nos apoyaremos en la técnica de “índice de Fisher ideal”, reconocida como un método superlativo para la generación de índices de precios al consumidor en la economía. Esta técnica combina dos elementos: la desviación de cada variable con respecto a una distribución de referencia y la magnitud total de gasto público de cada país. De esta forma se podrá apreciar tanto la medida en la que se aleja cada país respecto a un estándar deseado como el volumen natural de su inversión.

Para la creación de este índice se incluyen las variables “Gasto_Publico”, “Gasto_Defensa”, “Gasto_Educacion” y “Gasto_Salud” (importante: recordad que las últimas tres se presentan como porcentajes sobre el total).

# Calcular el gasto neto en cadea área de interés
datos <- datos %>% 
  mutate(
    Gasto_defensa_neto = Gasto_Defensa* Gasto_Publico / 100,
    Gasto_educacion_neto= Gasto_Educacion * Gasto_Publico / 100,
    Gasto_salud_neto = Gasto_Salud * Gasto_Publico/ 100)

# Calcular la desviación del gasto público con respecto a la distribución definida como ideal
# Suponiendo que la distribución ideal es el mayor valor de gasto público/PIB
distribucion_ideal_total <- max(datos$Gasto_Publico / datos$PIB)


datos <- datos %>% 
  mutate(
    desv_gasto_publico = distribucion_ideal_total - (Gasto_Publico/PIB) )

# Calcular el índice de Fisher ideal ponderando las desviaciones por la magnitud del gasto público
ponderaciones <- c(0.5,0.2, 0.15, 0.15, 0.05)

datos <- datos %>% 
  mutate(
    Gasto_publico = ponderaciones[1] * Gasto_Publico - ponderaciones[2] * desv_gasto_publico +
      ponderaciones[3] * Gasto_salud_neto  +
      ponderaciones[4] * Gasto_educacion_neto  +
      ponderaciones[5] * Gasto_defensa_neto 
  )

Es importante destacar que todas las puntuaciones de los países en esta categoría serán negativas, ya que se mide la distancia en la que se alejan de una situación ideal, y todas estarán por debajo del valor máximo establecido. No obstante, esta circunstancia no es relevante, ya que la asignación de los niveles se realizará en función de los percentiles y no de la magnitud absoluta de las puntuaciones.

En otras palabras, el hecho de que las puntuaciones sean negativas no afectará la interpretación de los resultados, ya que se utilizarán los percentiles para determinar la posición relativa de cada país en comparación con los demás. Esto permitirá asignar niveles y realizar comparaciones basadas en la distribución de los datos, sin importar el valor absoluto de las puntuaciones.

Para el resto de categorías se desarrollará un modelo de ponderaciones simples, es decir, implica atribuir valores numéricos a cada variable que representen su grado de relevancia o contribución en relación con el objetivo del análisis (lo que puede ayudar a priorizar y tener en cuenta las características más relevantes). A continuación, se resume el modelo para cada categoría donde se recoge las variables que describen el indice y las ponderaciones que se les han asignado:

  • Economía = 0.6 * PIB + 0.2 * Salario Medio + 0.15 * Indice de Poder Adquisitivo + 0.05 * Salario Minimo
  • Energético = 0.6 * Consumo GWh + 0.3 * CO2 per capita + 0.1 * Indice de Contaminacion
  • Bienestar = 0.3 * Indice Felicidad + 0.4 * Indice de calidad de vida - 0.4 * Indice de Criminalidad + 0.2 * Indice de Clima + 0.3* Indice de Sanidad

Creamos un nuevo dataframe donde se almacenan únicamente las columnas de interés con las transformaciones descritas.

nuevo_df <- datos %>%
  select(Pais, Indice_de_Costo_de_Vida, Gasto_Publico) %>%
  mutate(Economia = 0.6 * datos$PIB + 0.2 * datos$Salario_Medio + 0.15* datos$Indice_de_Poder_Adquisitivo + 0.05 * datos$Salario_Minimo,
         Energetico = 0.6*datos$Consumo_GWh + 0.3*datos$CO2_per_capita + 0.1 * datos$Indice_de_Contaminacion,
         Bienestar = 0.3 *datos$Indice_Felicidad + 0.4 * datos$Indice_de_Calidad_de_Vida  + (0.3*datos$Indice_de_Sanidad) + 0.2 * datos$Indice_de_Clima-(0.4*datos$Indice_de_Criminalidad))

4. Discretizar por percentiles

Al utilizar los percentiles como referencia para la discretización, aseguramos que cada nivel contenga una cantidad similar de datos, lo que nos proporciona una distribución equitativa y una representación adecuada de los valores en cada nivel.

# Calcular los percentiles de las variables Economia, Medioambiental y Bienestar
percentiles_economia <- quantile(nuevo_df$Economia, probs = c(0.000, 0.10, 0.30, 0.50, 0.7, 0.9, 1))
percentiles_energetico <- quantile(nuevo_df$Energetico, probs = c(0.000, 0.10, 0.30, 0.50, 0.7, 0.9, 1))
percentiles_bienestar <- quantile(nuevo_df$Bienestar, probs = c(0.000, 0.10, 0.30, 0.50, 0.7, 0.9, 1))
percentiles_gasto <- quantile(nuevo_df$Gasto_Publico, probs = c(0.000, 0.10, 0.30, 0.50, 0.7, 0.9, 1))
percentiles_vida <- quantile(nuevo_df$Indice_de_Costo_de_Vida, probs = c(0.000, 0.10, 0.30, 0.50, 0.7, 0.9, 1))

# Discretizar las variables Economía, Energético y Bienestar en los percentiles calculados
datos_rank = nuevo_df
datos_rank$Economia_discretizada <- cut(datos_rank$Economia, breaks = percentiles_economia, labels = FALSE)
datos_rank$Energetico_discretizada <- cut(datos_rank$Energetico, breaks = percentiles_energetico, labels = FALSE)
datos_rank$Bienestar_discretizada <- cut(datos_rank$Bienestar, breaks = percentiles_bienestar, labels = FALSE)
datos_rank$Gasto_publico_discretizada <- cut(datos_rank$Gasto_Publico, breaks = percentiles_gasto, labels = FALSE)
datos_rank$Indice_de_Costo_de_Vida_discretizada<- cut(datos_rank$Indice_de_Costo_de_Vida, breaks = percentiles_vida, labels = FALSE)

Vamos a etiquetar los valores faltantes (que se corresponden a los mínimos que ni siquiera entran en el percentil 0) como “Extremo bajo” para poder identificar y extraer conclusiones de los países asociados

Tambien se sustituye la escala de categorías para facilitar la interpretación

# Sustituir valores faltantes
datos_rank$Economia_discretizada <- ifelse(is.na(datos_rank$Economia_discretizada), "Extremo-bajo", datos_rank$Economia_discretizada)
datos_rank$Economia_discretizada <- factor(datos_rank$Economia_discretizada, levels = c(1, 2, 3, 4, 5, 6, "Extremo-bajo"), labels = c("Muy bajo", "Bajo", "Medio-bajo", "Medio-alto", "Alto", "Muy alto", "Extremo-bajo"))

datos_rank$Energetico_discretizada <- ifelse(is.na(datos_rank$Energetico_discretizada), "Extremo-bajo", datos_rank$Energetico_discretizada)
datos_rank$Energetico_discretizada = factor(datos_rank$Energetico_discretizada, levels = c(1, 2, 3, 4, 5, 6, "Extremo-bajo"), labels = c("Muy bajo", "Bajo", "Medio-bajo", "Medio-alto", "Alto", "Muy alto", "Extremo-bajo"))

datos_rank$Bienestar_discretizada <- ifelse(is.na(datos_rank$Bienestar_discretizada), "Extremo-bajo", datos_rank$Bienestar_discretizada)
datos_rank$Bienestar_discretizada = factor(datos_rank$Bienestar_discretizada, levels = c(1, 2, 3, 4, 5, 6, "Extremo-bajo"), labels = c("Muy bajo", "Bajo", "Medio-bajo", "Medio-alto", "Alto", "Muy alto", "Extremo-bajo"))

datos_rank$Gasto_publico_discretizada <- ifelse(is.na(datos_rank$Gasto_publico_discretizada), "Extremo-bajo", datos_rank$Gasto_publico_discretizada)
datos_rank$Gasto_publico_discretizada <- factor(datos_rank$Gasto_publico_discretizada, levels = c(1, 2, 3, 4, 5, 6, "Extremo-bajo"), labels = c("Muy bajo", "Bajo", "Medio-bajo", "Medio-alto", "Alto", "Muy alto", "Extremo-bajo"))

datos_rank$Indice_de_Costo_de_Vida_discretizada <- ifelse(is.na(datos_rank$Indice_de_Costo_de_Vida_discretizada), "Extremo-bajo", datos_rank$Indice_de_Costo_de_Vida_discretizada)
datos_rank$Indice_de_Costo_de_Vida_discretizada <- factor(datos_rank$Indice_de_Costo_de_Vida_discretizada, levels = c(1, 2, 3, 4, 5, 6, "Extremo-bajo"), labels = c("Muy bajo", "Bajo", "Medio-bajo", "Medio-alto", "Alto", "Muy alto", "Extremo-bajo"))

Antes de proceder con la presentación de los resultados, hemos optado por guardar los datos imputados, transformados y generados en un dataframe, de modo que puedan ser aprovechados en los objetivos restantes.

Df_nuevas_discretizadas = datos_rank
datos_normalizados = datos[,1:25]
datos_sin_faltantes = datos_imputados
save(Df_nuevas_discretizadas, datos_normalizados,datos_sin_faltantes, file = "base_objetivo1.Rdata")  

5. Representación por mapas

Que el principal objeto de estudio de la investigación sean los países del mundo explica que la representación de los resultados se haya inclinado en una primera instancia hacia la representación cartográfica. Para ello, debido a que la mayoría de las bibliotecas reconocidas en RStudio operan en inglés, se llevó a cabo una traducción preliminar mediante la concatenación con una base de datos especializada en traducciones.

# Descargar y cargar los datos del mapa del mundo
world_map <- map_data("world")

# Convertir los nombres de los países a minúsculas
datos_rank <- datos_rank %>%
  mutate(Pais = tolower(Pais))

# Capitalizar la primera letra de cada palabra en los nombres de los países
datos_rank$Pais <- str_to_title(datos_rank$Pais)

paises_conversion = read.csv("C:\\Users\\fanny\\Downloads\\paises_conversion.csv")
paises_conversion = paises_conversion[,c(1,2)]
colnames(paises_conversion) = c('Pais','Country')
datos_rank = left_join(datos_rank, paises_conversion)
## Joining with `by = join_by(Pais)`
# Rellenar manualmente las conversiones que no fueron captadas

datos_rank[datos_rank$Pais == "Bangladés",12] = 'Bangladesh'
datos_rank[datos_rank$Pais == "Catar",12] = 'Qatar'
datos_rank[datos_rank$Pais == "Corea Del Sur",12] = 'South Korea'
datos_rank[datos_rank$Pais == "Estados Unidos",12] = 'USA'
datos_rank[datos_rank$Pais == "Macedonia Del Norte",12] = 'North Macedonia'

Categoría Coste de Vida

Empezaremos con la generación de un gráfico de mapas que muestra el índice de costo de vida de diferentes países, utilizando colores para representar diferentes categorías de costos de vida. Esto permite visualizar y comparar rápidamente las variaciones en el costo de vida entre las regiones geográficas. Para ello, seguiremos las siguientes acciones:

  • Primero se realiza combinación de datos entre el dataframe “datos_rank” y el dataframe “world_map” utilizando la columna “Country” en “datos_mapa_coste” y la columna “region” en “world_map”. Esto permite asociar cada país con su correspondiente región geográfica.

  • Luego, se define una escala de colores para cada categoría del índice de costo de vida. Cada categoría tiene asignado un color específico.

  • A continuación, se crea el gráfico de mapas utilizando la biblioteca ggplot2. Se establecen las estéticas del gráfico, como las coordenadas x e y, el grupo y el relleno basado en la columna “Indice_de_Costo_de_Vida_discretizada” del dataframe “datos_mapa_coste”.

  • Se agregan polígonos al gráfico para representar las regiones geográficas, con bordes de color negro y un tamaño de 0.2. Se ajusta la proporción de los ejes para que coincidan y se configura el tema del gráfico como “void” para eliminar elementos de fondo innecesarios.

  • Finalmente, se establece la escala de colores del gráfico utilizando los valores de la variable “colores” y se agrega un título al gráfico que indica “Coste de vida”.

    El resultado se muestra a continuación.

# Crear un nuevo dataframe que contenga los datos de interés

datos_mapa_coste <- datos_rank %>%
  select(Country, Indice_de_Costo_de_Vida_discretizada, Indice_de_Costo_de_Vida ) %>%
  distinct() %>%
  full_join(world_map, by = c("Country" = "region"))
## Warning in full_join(., world_map, by = c(Country = "region")): Each row in `x` is expected to match at most 1 row in `y`.
## ℹ Row 1 of `x` matches multiple rows.
## ℹ If multiple matches are expected, set `multiple = "all"` to silence this
##   warning.
# Definir los colores de cada categoría
colores <- c("Extremo-bajo" = "#FF0000",
             "Muy bajo" = "#FF8000",
             "Bajo" = "#FFFF00",
             "Medio-bajo" = "#00FF80",
             "Medio-alto" = "#00FFFF",
             "Alto" = "#0080FF",
             "Muy alto" = "#FF00FF")

# Crear el gráfico de mapas utilizando ggplot2
ggplot(datos_mapa_coste, aes(x = long, y = lat, group = group, fill = Indice_de_Costo_de_Vida_discretizada )) +
  geom_polygon(color = "black", size = 0.2) +
  coord_equal() +
  theme_void() +
  scale_fill_manual(values = colores, na.value = "white") +
  labs(title = "Coste de vida")
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.

A pesar de que la representación de los niveles de la categoría se realiza de manera adecuada y estéticamente acertada, la proporción de tamaño geográfico de cada región distorsiona la percepción de los resultados. En otras palabras, si bien es fácil y casi instantáneo identificar la clasificación de los países más grandes, los resultados de los países más pequeños pueden pasar desapercibidos. La impresión general de la categoría puede quedar sesgada.

Es entonces cuando exploramos la posibilidad de representar los resultados en mapas interactivos en lugar de mapas estáticos.

Para conseguirlo, comenzaremos por realizar una serie de transformaciones al nombre de los países (al discrepar la nomenglatura entre las librerías empleadas) y asociaremos a cada nivel del índice el mismo color que fue empleado en la representación anterior para facilitar la interpretación.

pal = c("#FF0000","#FF8000", "#FFFF00", "#00FF80", "#00FFFF", "#0080FF","#FF00FF" )

datos_mapa_coste[datos_mapa_coste$Country == "South Korea",1] = 'Korea'
datos_mapa_coste[datos_mapa_coste$Country == "North Macedonia",1] = 'Macedonia'
datos_mapa_coste[datos_mapa_coste$Country == "USA",1] = 'United States'
datos_mapa_coste[datos_mapa_coste$Country == "Russia",1] = 'Russian Federation'

datos_mapa_coste$color <- ifelse(datos_mapa_coste$Indice_de_Costo_de_Vida_discretizada == "Extremo-bajo", "#FF0000", ifelse(datos_mapa_coste$Indice_de_Costo_de_Vida_discretizada == "Muy bajo", "#FF8000", ifelse(datos_mapa_coste$Indice_de_Costo_de_Vida_discretizada == "Bajo", "#FFFF00", ifelse(datos_mapa_coste$Indice_de_Costo_de_Vida_discretizada == "Medio-bajo", "#00FF80",
 ifelse(datos_mapa_coste$Indice_de_Costo_de_Vida_discretizada == "Medio-alto", "#00FFFF",
 ifelse(datos_mapa_coste$Indice_de_Costo_de_Vida_discretizada == "Alto", "#0080FF", ifelse(datos_mapa_coste$Indice_de_Costo_de_Vida_discretizada == "Muy alto", "#FF00FF", NA)))))))

Para el desarrollo de la representación interactiva nos apoyaremos de la librería leaflet. El código tiene como objetivo principal crear un mapa interactivo que visualice el índice de costo de vida de diferentes países. Utiliza datos geográficos en formato GeoJSON y datos del índice de costo de vida. El mapa muestra los polígonos geográficos coloreados de acuerdo con el nivel de costo de vida, representado por colores específicos. Además, se agrega una leyenda para interpretar los colores utilizados en el mapa. El resultado final es un mapa interactivo que proporciona una representación visual del índice de costo de vida en distintas regiones geográficas.

poligonos = read.csv("C:\\Users\\fanny\\Downloads\\ne_110m_admin_0_countries_geojson.csv")
poligonos <- poligonos %>%
  select(geojson, NAME_LONG)


datos_geojson_coste <- datos_mapa_coste %>%
  select(Country, Indice_de_Costo_de_Vida_discretizada, Indice_de_Costo_de_Vida, color ) %>%
  distinct() %>%
  left_join(poligonos, by = c("Country" = "NAME_LONG"))

# Eliminamos faltantes
datos_geojson_coste <- datos_geojson_coste[complete.cases(datos_geojson_coste), ]

map_data_coste <- lapply(datos_geojson_coste$geojson, function(x) jsonlite::fromJSON(x))

# Crear un mapa leaflet
map_coste <- leaflet() %>%
  addTiles() # Añadir capa de teselas base

for (i in seq_along(map_data_coste)) {
  if (!is.null(map_data_coste[[i]])) {
    map_coste <- map_coste %>%
      addGeoJSON(map_data_coste[[i]], fillColor = datos_geojson_coste$color[i], fillOpacity = 0.5, weight = 1)
  }
}
# Definir los valores discretizados y sus correspondientes colores
leyenda <- data.frame(
  Indice_de_Costo_de_Vida_discretizada = c("Extremo-bajo","Muy bajo" ,"Bajo" ,"Medio-bajo","Medio-alto" ,"Alto" ,"Muy alto" ),
  color = pal)

map_coste <- addLegend(
  map_coste,
  position = "bottomright",
  colors = leyenda$color,
  labels = leyenda$Indice_de_Costo_de_Vida_discretizada,
  title = "Indice de coste de vida"
)


# Mostrar el mapa
map_coste

Para el resto de categorías se seguirá la misma linea de acción que se ha detallado en este apartado.

Categoría Económica

# Crear un nuevo dataframe que contenga los datos de interés
datos_rank[datos_rank$Pais == "Estados Unidos",12] = 'USA'
datos_mapa_econ <- datos_rank %>%
  select(Country, Economia_discretizada, Economia) %>%
  distinct() %>%
  full_join(world_map, by = c("Country" = "region"))
## Warning in full_join(., world_map, by = c(Country = "region")): Each row in `x` is expected to match at most 1 row in `y`.
## ℹ Row 1 of `x` matches multiple rows.
## ℹ If multiple matches are expected, set `multiple = "all"` to silence this
##   warning.
# Definir los colores de cada categoría
colores <- c("Extremo-bajo" = "#FF0000",
             "Muy bajo" = "#FF8000",
             "Bajo" = "#FFFF00",
             "Medio-bajo" = "#00FF80",
             "Medio-alto" = "#00FFFF",
             "Alto" = "#0080FF",
             "Muy alto" = "#FF00FF")

# Crear el gráfico de mapas utilizando ggplot2
ggplot(datos_mapa_econ, aes(x = long, y = lat, group = group, fill = Economia_discretizada)) +
  geom_polygon(color = "black", size = 0.2) +
  coord_equal() +
  theme_void() +
  scale_fill_manual(values = colores, na.value = "white") +
  labs(title = "Categoría económica")

datos_mapa_econ[datos_mapa_econ$Country == "South Korea",1] = 'Korea'
datos_mapa_econ[datos_mapa_econ$Country == "North Macedonia",1] = 'Macedonia'
datos_mapa_econ[datos_mapa_econ$Country == "USA",1] = 'United States'
datos_mapa_econ[datos_mapa_econ$Country == "Russia",1] = 'Russian Federation'
datos_mapa_econ$color <- ifelse(datos_mapa_econ$Economia_discretizada == "Extremo-bajo", "#FF0000", ifelse(datos_mapa_econ$Economia_discretizada == "Muy bajo", "#FF8000", ifelse(datos_mapa_econ$Economia_discretizada == "Bajo", "#FFFF00", ifelse(datos_mapa_econ$Economia_discretizada == "Medio-bajo", "#00FF80",
 ifelse(datos_mapa_econ$Economia_discretizada == "Medio-alto", "#00FFFF",
 ifelse(datos_mapa_econ$Economia_discretizada == "Alto", "#0080FF", ifelse(datos_mapa_econ$Economia_discretizada == "Muy alto", "#FF00FF", NA)))))))


datos_geojson_econ <- datos_mapa_econ %>%
  select(Country, Economia_discretizada, Economia, color ) %>%
  distinct() %>%
  left_join(poligonos, by = c("Country" = "NAME_LONG"))

# Eliminamos faltantes
datos_geojson_econ <- datos_geojson_econ[complete.cases(datos_geojson_econ), ]

map_data_econ <- lapply(datos_geojson_econ$geojson, function(x) jsonlite::fromJSON(x))

# Crear un mapa leaflet
map_econ <- leaflet() %>%
  addTiles() # Añadir capa de teselas base

for (i in seq_along(map_data_econ)) {
  if (!is.null(map_data_econ[[i]])) {
    map_econ <- map_econ %>%
      addGeoJSON(map_data_econ[[i]], fillColor = datos_geojson_econ$color[i], fillOpacity = 0.5, weight = 1)
  }
}
# Definir los valores discretizados y sus correspondientes colores
leyenda <- data.frame(
  Economia_discretizada = c("Extremo-bajo","Muy bajo" ,"Bajo" ,"Medio-bajo","Medio-alto" ,"Alto" ,"Muy alto" ),
  color = pal)

map_econ<- addLegend(
  map_econ,
  position = "bottomright",
  colors = leyenda$color,
  labels = leyenda$Economia_discretizada,
  title = "Nivel económico"
)

# Mostrar el mapa
map_econ

Categoría Energética

# Crear un nuevo dataframe que contenga los datos de interés

datos_mapa_ener <- datos_rank %>%
  select(Country, Energetico_discretizada, Energetico) %>%
  distinct() %>%
  full_join(world_map, by = c("Country" = "region"))
## Warning in full_join(., world_map, by = c(Country = "region")): Each row in `x` is expected to match at most 1 row in `y`.
## ℹ Row 1 of `x` matches multiple rows.
## ℹ If multiple matches are expected, set `multiple = "all"` to silence this
##   warning.
# Definir los colores de cada categoría
colores <- c("Extremo-bajo" = "#FF0000",
             "Muy bajo" = "#FF8000",
             "Bajo" = "#FFFF00",
             "Medio-bajo" = "#00FF80",
             "Medio-alto" = "#00FFFF",
             "Alto" = "#0080FF",
             "Muy alto" = "#FF00FF")

# Crear el gráfico de mapas utilizando ggplot2
ggplot(datos_mapa_ener, aes(x = long, y = lat, group = group, fill = Energetico_discretizada)) +
  geom_polygon(color = "black", size = 0.2) +
  coord_equal() +
  theme_void() +
  scale_fill_manual(values = colores, na.value = "white") +
  labs(title = "Categoría energética")

datos_mapa_ener[datos_mapa_ener$Country == "South Korea",1] = 'Korea'
datos_mapa_ener[datos_mapa_ener$Country == "North Macedonia",1] = 'Macedonia'
datos_mapa_ener[datos_mapa_ener$Country == "USA",1] = 'United States'
datos_mapa_ener[datos_mapa_ener$Country == "Russia",1] = 'Russian Federation'
datos_mapa_ener$color <- ifelse(datos_mapa_ener$Energetico_discretizada == "Extremo-bajo", "#FF0000", ifelse(datos_mapa_ener$Energetico_discretizada == "Muy bajo", "#FF8000", ifelse(datos_mapa_ener$Energetico_discretizada == "Bajo", "#FFFF00", ifelse(datos_mapa_ener$Energetico_discretizada == "Medio-bajo", "#00FF80",
 ifelse(datos_mapa_ener$Energetico_discretizada == "Medio-alto", "#00FFFF",
 ifelse(datos_mapa_ener$Energetico_discretizada == "Alto", "#0080FF", ifelse(datos_mapa_ener$Energetico_discretizada == "Muy alto", "#FF00FF", NA)))))))


datos_geojson_ener <- datos_mapa_ener %>%
  select(Country, Energetico_discretizada, Energetico, color ) %>%
  distinct() %>%
  left_join(poligonos, by = c("Country" = "NAME_LONG"))

# Eliminamos faltantes
datos_geojson_ener <- datos_geojson_ener[complete.cases(datos_geojson_ener), ]

map_data_ener <- lapply(datos_geojson_ener$geojson, function(x) jsonlite::fromJSON(x))

# Crear un mapa leaflet
map_ener <- leaflet() %>%
  addTiles() # Añadir capa de teselas base

for (i in seq_along(map_data_ener)) {
  if (!is.null(map_data_ener[[i]])) {
    map_ener <- map_ener %>%
      addGeoJSON(map_data_ener[[i]], fillColor = datos_geojson_ener$color[i], fillOpacity = 0.5, weight = 1)
  }
}
# Definir los valores discretizados y sus correspondientes colores
leyenda <- data.frame(
  Energetico_discretizada = c("Extremo-bajo","Muy bajo" ,"Bajo" ,"Medio-bajo","Medio-alto" ,"Alto" ,"Muy alto" ),
  color = pal)

map_ener<- addLegend(
  map_ener,
  position = "bottomright",
  colors = leyenda$color,
  labels = leyenda$Energetico_discretizada,
  title = "Nivel de consumo energético"
)

# Mostrar el mapa
map_ener

Categoría Bienestar

#Crear un nuevo dataframe que contenga los datos de interés

datos_mapa_bien <- datos_rank %>%
  select(Country, Bienestar_discretizada, Bienestar) %>%
  distinct() %>%
  full_join(world_map, by = c("Country" = "region"))
## Warning in full_join(., world_map, by = c(Country = "region")): Each row in `x` is expected to match at most 1 row in `y`.
## ℹ Row 1 of `x` matches multiple rows.
## ℹ If multiple matches are expected, set `multiple = "all"` to silence this
##   warning.
# Definir los colores de cada categoría
colores <- c("Extremo-bajo" = "#FF0000",
             "Muy bajo" = "#FF8000",
             "Bajo" = "#FFFF00",
             "Medio-bajo" = "#00FF80",
             "Medio-alto" = "#00FFFF",
             "Alto" = "#0080FF",
             "Muy alto" = "#FF00FF")

#Crear el gráfico de mapas utilizando ggplot2
ggplot(datos_mapa_bien, aes(x = long, y = lat, group = group, fill = Bienestar_discretizada)) +
  geom_polygon(color = "black", size = 0.2) +
  coord_equal() +
  theme_void() +
  scale_fill_manual(values = colores, na.value = "white") +
  labs(title = "Categoría bienestar")

datos_mapa_bien[datos_mapa_bien$Country == "South Korea",1] = 'Korea'
datos_mapa_bien[datos_mapa_bien$Country == "North Macedonia",1] = 'Macedonia'
datos_mapa_bien[datos_mapa_bien$Country == "USA",1] = 'United States'
datos_mapa_bien[datos_mapa_bien$Country == "Russia",1] = 'Russian Federation'
datos_mapa_bien$color <- ifelse(datos_mapa_bien$Bienestar_discretizada == "Extremo-bajo", "#FF0000", ifelse(datos_mapa_bien$Bienestar_discretizada == "Muy bajo", "#FF8000", ifelse(datos_mapa_bien$Bienestar_discretizada == "Bajo", "#FFFF00", ifelse(datos_mapa_bien$Bienestar_discretizada == "Medio-bajo", "#00FF80",
 ifelse(datos_mapa_bien$Bienestar_discretizada == "Medio-alto", "#00FFFF",
 ifelse(datos_mapa_bien$Bienestar_discretizada == "Alto", "#0080FF", ifelse(datos_mapa_bien$Bienestar_discretizada == "Muy alto", "#FF00FF", NA)))))))


datos_geojson_bien <- datos_mapa_bien%>%
  select(Country, Bienestar_discretizada, Bienestar, color ) %>%
  distinct() %>%
  left_join(poligonos, by = c("Country" = "NAME_LONG"))

# Eliminamos faltantes
datos_geojson_bien <- datos_geojson_bien[complete.cases(datos_geojson_bien), ]

map_data_bien <- lapply(datos_geojson_bien$geojson, function(x) jsonlite::fromJSON(x))

# Crear un mapa leaflet
map_bien <- leaflet() %>%
  addTiles() # Añadir capa de teselas base

for (i in seq_along(map_data_bien)) {
  if (!is.null(map_data_bien[[i]])) {
    map_bien <- map_bien %>%
      addGeoJSON(map_data_bien[[i]], fillColor = datos_geojson_bien$color[i], fillOpacity = 0.5, weight = 1)
  }
}
# Definir los valores discretizados y sus correspondientes colores
leyenda <- data.frame(
  Bienestar_discretizada = c("Extremo-bajo","Muy bajo" ,"Bajo" ,"Medio-bajo","Medio-alto" ,"Alto" ,"Muy alto" ),
  color = pal)

map_bien<- addLegend(
  map_bien,
  position = "bottomright",
  colors = leyenda$color,
  labels = leyenda$Bienestar_discretizada,
  title = "Nivel de bienestar"
)

# Mostrar el mapa
map_bien

Categoría Gasto Público

# Crear un nuevo dataframe que contenga los datos de interés

datos_mapa_gasto <- datos_rank %>%
  select(Country, Gasto_publico_discretizada, Gasto_Publico) %>%
  distinct() %>%
  full_join(world_map, by = c("Country" = "region"))
## Warning in full_join(., world_map, by = c(Country = "region")): Each row in `x` is expected to match at most 1 row in `y`.
## ℹ Row 1 of `x` matches multiple rows.
## ℹ If multiple matches are expected, set `multiple = "all"` to silence this
##   warning.
# Definir los colores de cada categoría
colores <- c("Extremo-bajo" = "#FF0000",
             "Muy bajo" = "#FF8000",
             "Bajo" = "#FFFF00",
             "Medio-bajo" = "#00FF80",
             "Medio-alto" = "#00FFFF",
             "Alto" = "#0080FF",
             "Muy alto" = "#FF00FF")

# Crear el gráfico de mapas utilizando ggplot2
ggplot(datos_mapa_gasto, aes(x = long, y = lat, group = group, fill = Gasto_publico_discretizada)) +
  geom_polygon(color = "black", size = 0.2) +
  coord_equal() +
  theme_void() +
  scale_fill_manual(values = colores, na.value = "white") +
  labs(title = "Categoría de gasto público")

datos_mapa_gasto[datos_mapa_gasto$Country == "South Korea",1] = 'Korea'
datos_mapa_gasto[datos_mapa_gasto$Country == "North Macedonia",1] = 'Macedonia'
datos_mapa_gasto[datos_mapa_gasto$Country == "USA",1] = 'United States'
datos_mapa_gasto[datos_mapa_gasto$Country == "Russia",1] = 'Russian Federation'
datos_mapa_gasto$color <- ifelse(datos_mapa_gasto$Gasto_publico_discretizada == "Extremo-bajo", "#FF0000", ifelse(datos_mapa_gasto$Gasto_publico_discretizada == "Muy bajo", "#FF8000", ifelse(datos_mapa_gasto$Gasto_publico_discretizada == "Bajo", "#FFFF00", ifelse(datos_mapa_gasto$Gasto_publico_discretizada == "Medio-bajo", "#00FF80",
 ifelse(datos_mapa_gasto$Gasto_publico_discretizada == "Medio-alto", "#00FFFF",
 ifelse(datos_mapa_gasto$Gasto_publico_discretizada == "Alto", "#0080FF", ifelse(datos_mapa_gasto$Gasto_publico_discretizada == "Muy alto", "#FF00FF", NA)))))))


datos_geojson_gasto <- datos_mapa_gasto %>%
  select(Country, Gasto_publico_discretizada,Gasto_Publico, color ) %>%
  distinct() %>%
  left_join(poligonos, by = c("Country" = "NAME_LONG"))

# Eliminamos faltantes
datos_geojson_gasto <- datos_geojson_gasto[complete.cases(datos_geojson_gasto), ]

map_data_gasto <- lapply(datos_geojson_gasto$geojson, function(x) jsonlite::fromJSON(x))

# Crear un mapa leaflet
map_gasto <- leaflet() %>%
  addTiles() # Añadir capa de teselas base

for (i in seq_along(map_data_gasto)) {
  if (!is.null(map_data_gasto[[i]])) {
    map_gasto <- map_gasto %>%
      addGeoJSON(map_data_gasto[[i]], fillColor = datos_geojson_gasto$color[i], fillOpacity = 0.5, weight = 1)
  }
}
# Definir los valores discretizados y sus correspondientes colores
leyenda <- data.frame(
  Gasto_discretizada = c("Extremo-bajo","Muy bajo" ,"Bajo" ,"Medio-bajo","Medio-alto" ,"Alto" ,"Muy alto" ),
  color = pal)

map_gasto<- addLegend(
  map_gasto,
  position = "bottomright",
  colors = leyenda$color,
  labels = leyenda$Gasto_discretizada,
  title = "Nivel de gasto público"
)

# Mostrar el mapa
map_gasto

6. Rankings

Para introducirnos en la comprobación de la hipótesis de la relación entre el coste de vida y las categorías definidas, tarea que se abordará con la aplicación de distintas técnicas estadísticas en otros objetivos del estudio, se ha decidido ilustrar la lista de los 10 países con las puntuaciones más altas y bajas en cada ámbito con el fin de destacar a la vez su posicionamiento en cuanto al coste de vida.

Económico

colores <- c("Muy alto" = "#a60039", "Alto" = "#ff004e", "Medio-alto" = "#FCA9C2","Medio-bajo" = "#ACFEF9", "Bajo" ="#1be7dc", "Muy bajo" = "#1a4c64", "Extremo-bajo" = "#FFC240")

econ_top10 <- top_n( datos_rank, 10, Economia)
# Gráfico base
ggEcon <- ggplot(econ_top10, 
                aes( x = reorder(Pais,Economia),
                     y = Economia, 
                     fill = Indice_de_Costo_de_Vida_discretizada) ) +
          geom_bar( stat = "identity" ) +
          scale_fill_manual( name = "Coste de Vida",values = colores) +
          ylim( 0, 3 ) +
          labs( title = "Ranking económico TOP10") +
          coord_flip( ) 
# Editarlo 
ggEcon + theme( axis.title.x = element_blank(),
               axis.title.y = element_blank(),
               axis.text.x = element_text(size = 8),
               axis.text.y = element_text(size = 12),
               plot.title = element_text( size = 20, colour = "grey39", face = "bold"),
               plot.subtitle = element_text( size = 15, colour = "grey39"),
               legend.text = element_text(size = 10),
               legend.title = element_text(size = 12),
               legend.position = "right" )

econ_last10 <- datos_rank %>% 
  arrange(Economia) %>% 
  head(10)

## Gráfico base
ggEcon <- ggplot(econ_last10, aes(x = reorder(Pais,Economia), y = Economia, fill = Indice_de_Costo_de_Vida_discretizada)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(name = "Coste de Vida", values = colores) +
  ylim(-2, 0) +
  labs(title = "Ranking económico LAST10") +
  coord_flip()

# Editarlo 
ggEcon + theme( axis.title.x = element_blank(),
               axis.title.y = element_blank(),
               axis.text.x = element_text(size = 8),
               axis.text.y = element_text(size = 12),
               plot.title = element_text( size = 20, colour = "grey39", face = "bold"),
               plot.subtitle = element_text( size = 15, colour = "grey39"),
               legend.text = element_text(size = 10),
               legend.title = element_text(size = 12),
               legend.position = "right" )

Energético

ener_top10 <- top_n( datos_rank, 10, Energetico)
# Gráfico base
ggEner <- ggplot(ener_top10, 
                aes( x = reorder( Pais,Energetico),
                     y = Energetico, 
                     fill = Indice_de_Costo_de_Vida_discretizada ) ) +
          geom_bar( stat = "identity" ) +
          scale_fill_manual( name = "Coste de Vida",values = colores) +
          ylim( 0, 3 ) +
          labs( title = "Ranking energético TOP10") +
          coord_flip( ) 
# Editarlo 
ggEner + theme( axis.title.x = element_blank(),
               axis.title.y = element_blank(),
               axis.text.x = element_text(size = 8),
               axis.text.y = element_text(size = 12),
               plot.title = element_text( size = 20, colour = "grey39", face = "bold"),
               plot.subtitle = element_text( size = 15, colour = "grey39"),
               legend.text = element_text(size = 10),
               legend.title = element_text(size = 12),
               legend.position = "right" )

ener_last10 <- datos_rank %>% 
  arrange(Energetico) %>% 
  head(10)

## Gráfico base
ggEner <- ggplot(ener_last10, aes(x = reorder(Pais,Energetico), y = Energetico, fill = Indice_de_Costo_de_Vida_discretizada)) +
  geom_bar(stat = "identity") +
  scale_fill_manual(name = "Coste de Vida", values = colores) +
  ylim(-3, 0) +
  labs(title = "Ranking energético LAST10") +
  coord_flip()

# Editarlo 
ggEner + theme( axis.title.x = element_blank(),
               axis.title.y = element_blank(),
               axis.text.x = element_text(size = 8),
               axis.text.y = element_text(size = 12),
               plot.title = element_text( size = 20, colour = "grey39", face = "bold"),
               plot.subtitle = element_text( size = 15, colour = "grey39"),
               legend.text = element_text(size = 10),
               legend.title = element_text(size = 12),
               legend.position = "right" )

Bienestar

bien_top10 <- top_n( datos_rank, 10, Bienestar)
# Gráfico base
ggBien <- ggplot(bien_top10, 
                aes( x = reorder( Pais,Bienestar),
                     y = Bienestar, 
                     fill = Indice_de_Costo_de_Vida_discretizada ) ) +
          geom_bar( stat = "identity" ) +
          scale_fill_manual( name = "Coste de Vida", values = colores) +
          ylim( 0, 3 ) +
          labs( title = "Ranking bienestar TOP10") +
          coord_flip( ) 
# Editarlo 
ggBien + theme( axis.title.x = element_blank(),
               axis.title.y = element_blank(),
               axis.text.x = element_text(size = 8),
               axis.text.y = element_text(size = 12),
               plot.title = element_text( size = 20, colour = "grey39", face = "bold"),
               plot.subtitle = element_text( size = 15, colour = "grey39"),
               legend.text = element_text(size = 10),
               legend.title = element_text(size = 12),
               legend.position = "right" )

bien_last10 <- datos_rank %>% 
  arrange(Bienestar) %>% 
  head(10)
# Gráfico base
ggBien <- ggplot(bien_last10, 
                aes( x = reorder( Pais,Bienestar),
                     y = Bienestar, 
                     fill = Indice_de_Costo_de_Vida_discretizada ) ) +
          geom_bar( stat = "identity" ) +
          scale_fill_manual( name = "Coste de Vida", values = colores) +
          ylim( -3, 0 ) +
          labs( title = "Ranking bienestar LAST10") +
          coord_flip( ) 
# Editarlo 
ggBien + theme( axis.title.x = element_blank(),
               axis.title.y = element_blank(),
               axis.text.x = element_text(size = 8),
               axis.text.y = element_text(size = 12),
               plot.title = element_text( size = 20, colour = "grey39", face = "bold"),
               plot.subtitle = element_text( size = 15, colour = "grey39"),
               legend.text = element_text(size = 10),
               legend.title = element_text(size = 12),
               legend.position = "right" )

Gasto Público

gasto_top10 <- top_n( datos_rank, 10, Gasto_Publico)
# Gráfico base
ggGasto <- ggplot(gasto_top10, 
                aes( x = reorder( Pais,Gasto_Publico),
                     y = Gasto_Publico, 
                     fill = Indice_de_Costo_de_Vida_discretizada ) ) +
          geom_bar( stat = "identity" ) +
          scale_fill_manual( name = "Coste de Vida", values = colores) +
          ylim( 0, 3 ) +
          labs( title = "Ranking gasto público TOP10") +
          coord_flip( ) 
# Editarlo 
ggGasto + theme( axis.title.x = element_blank(),
               axis.title.y = element_blank(),
               axis.text.x = element_text(size = 8),
               axis.text.y = element_text(size = 12),
               plot.title = element_text( size = 20, colour = "grey39", face = "bold"),
               plot.subtitle = element_text( size = 15, colour = "grey39"),
               legend.text = element_text(size = 10),
               legend.title = element_text(size = 12),
               legend.position = "right" )

gasto_last10 <- datos_rank %>% 
  arrange(Gasto_Publico) %>% 
  head(10)
# Gráfico base
ggGasto<- ggplot(gasto_last10, 
                aes( x = reorder( Pais,Gasto_Publico),
                     y = Gasto_Publico, 
                     fill = Indice_de_Costo_de_Vida_discretizada ) ) +
          geom_bar( stat = "identity" ) +
          scale_fill_manual( name = "Coste de Vida", values = colores) +
          ylim( -3, 0 ) +
          labs( title = "Ranking gasto público LAST10") +
          coord_flip( ) 
# Editarlo 
ggGasto + theme( axis.title.x = element_blank(),
               axis.title.y = element_blank(),
               axis.text.x = element_text(size = 8),
               axis.text.y = element_text(size = 12),
               plot.title = element_text( size = 20, colour = "grey39", face = "bold"),
               plot.subtitle = element_text( size = 15, colour = "grey39"),
               legend.text = element_text(size = 10),
               legend.title = element_text(size = 12),
               legend.position = "right" )

Otras visualizaciones

# install.packages("ggwordcloud")
library(ggwordcloud)

set.seed(1)
ggplot(datos_rank, aes(label = Pais, size = Economia, color = Indice_de_Costo_de_Vida)) +
  geom_text_wordcloud() +
  scale_size_area(max_size = 8) +
  theme_minimal() 
## Warning in png(filename = tmp_file, width = gw_pix, height = gh_pix, res =
## dev_dpi, : 'width=8, height=8' are unlikely values in pixels

datos_rank[datos_rank$Pais == "Estados Unidos",12] = 'United States'
datos_rank %>% 
  e_charts(Country) %>% 
  e_map(Indice_de_Costo_de_Vida) %>% 
  e_visual_map(Indice_de_Costo_de_Vida)  %>%
  e_title("Coste de vida", "Por País") %>% 
  e_theme("infographic")
datos_rank %>% 
  e_charts(Country) %>% 
  e_map(Economia) %>% 
  e_visual_map(Economia)  %>%
  e_title("Economia", "Por País") %>% 
  e_theme("infographic")
datos_rank %>% 
  e_charts(Country) %>% 
  e_map(Energetico) %>% 
  e_visual_map(Energetico)  %>%
  e_title("Energético", "Por País") %>% 
  e_theme("infographic")
datos_rank %>% 
  e_charts(Country) %>% 
  e_map(Bienestar) %>% 
  e_visual_map(Bienestar)  %>%
  e_title("Economia", "Por País") %>% 
  e_theme("infographic")
datos_rank %>% 
  e_charts(Country) %>% 
  e_map(Gasto_Publico) %>% 
  e_visual_map(Gasto_Publico)  %>%
  e_title("Gasto Público", "Por País") %>% 
  e_theme("infographic")