Este documento se trata de un análisis descriptivo de la base de datos “Cost of Living Index” hecha por Numbeo, la cual provee los índices de costos de vida de diferentes países en lo que va del año 2024. Un índice de costo de vida es una medida que compara los costos promedio de bienes y servicios básicos en distintos lugares e intervalos de tiempo, con el objetivo de evaluar cuán caro es vivir en un país, región o ciudad en comparación con otros lugares dentro de la misma categoría.
Los índices de costo de vida en esta base de datos están comparados con la ciudad de Nueva York (NYC), la cual se usa como caso base asignándole un índice de 100. Por ejemplo, si un país tiene un índice de costo de vida de 120, se estima que es un 20% más caro vivir en dicho país en comparación con Nueva York. Asimismo, si el índice es de 80, se estima que es un 20% más barato vivir en ese país en comparación con Nueva York.
Una familia de cuatro miembros tiene un costo mensual estimado de $6,074.40 sin alquiler.
Los costos mensuales estimados de una persona soltera son $1,640.90 sin alquiler.
Toda la información y datos presentados en este análisis han sido obtenidos de la base de datos de Numbeo (Numbeo, 2024).
##
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
## Cargando paquete requerido: Rcpp
## ##
## ## Amelia II: Multiple Imputation
## ## (Version 1.8.2, built: 2024-04-10)
## ## Copyright (C) 2005-2024 James Honaker, Gary King and Matthew Blackwell
## ## Refer to http://gking.harvard.edu/amelia/ for more information
## ##
Para comenzar el analisis, es necesario identificar las caracteristicas basicas de la base de datos con la que estamos trabajando, empezando por la dimensión de la base de datos:
dim(datosReadr)
## [1] 121 8
Esta base esta compuesta por 121 filas que representan a los paises y 8 columnas que representan a las variables.
Los nombres de las variables son las siguientes:
names(datosReadr)
## [1] "Rank" "Country"
## [3] "Cost of Living Index" "Rent Index"
## [5] "Cost of Living Plus Rent Index" "Groceries Index"
## [7] "Restaurant Price Index" "Local Purchasing Power Index"
El tipo de variable y ejemplos de los datos que estas reciben aparecen a continuacion:
glimpse(datosReadr)
## Rows: 121
## Columns: 8
## $ Rank <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12…
## $ Country <chr> "Switzerland", "Bahamas", "Iceland", …
## $ `Cost of Living Index` <dbl> 101.1, 85.0, 83.0, 76.7, 76.6, 76.0, …
## $ `Rent Index` <dbl> 46.5, 36.7, 39.2, 67.2, 19.0, 26.2, 2…
## $ `Cost of Living Plus Rent Index` <dbl> 74.9, 61.8, 62.0, 72.1, 48.9, 52.1, 5…
## $ `Groceries Index` <dbl> 109.1, 81.6, 88.4, 74.6, 80.8, 79.0, …
## $ `Restaurant Price Index` <dbl> 97.0, 83.3, 86.8, 50.4, 69.4, 73.5, 8…
## $ `Local Purchasing Power Index` <dbl> 158.7, 54.6, 120.3, 111.1, 43.5, 114.…
La base de datos utiliza 8 variables, 7 siendo numericas (dbl) y solo una siendo categorica (chr):
Rank (dbl): En la base de datos los paises estan ordenados de mayor costo de vida a menor costo de vida, la variable ‘Rank’ indica que posicion ocupa el pais en cuestión.
Country: Esta variable indica el nombre del país en cuestión, siendo esta la unica variable categorica de la base de datos ya que representa diferentes países, cada uno de los cuales es una categoría distinta sin un valor numérico asociado.
Cost of Living Index (dbl): Este índice indica los precios relativos de bienes de consumo como alimentos, restaurantes, transporte y servicios públicos, excluyendo los costos de alojamiento.
summary(datosReadr$"Cost of Living Index")
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 18.80 30.20 39.50 43.56 52.80 101.10
summary(datosReadr$"Rent Index")
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2.40 8.50 12.40 16.05 20.10 67.20
summary(datosReadr$"Cost of Living Plus Rent Index")
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 11.10 19.80 27.00 30.36 37.00 74.90
summary(datosReadr$"Groceries Index")
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 17.50 31.60 40.50 44.23 53.70 109.10
summary(datosReadr$"Restaurant Price Index")
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 12.80 21.60 33.10 36.47 47.20 97.00
summary(datosReadr$"Local Purchasing Power Index")
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 2.30 34.80 50.60 65.09 99.40 182.50
Ahora calculemos la desviación estandar y el coeficiente de variacion de cada variable:
variables <- c('Cost of Living Index', 'Rent Index', 'Cost of Living Plus Rent Index', 'Groceries Index', 'Restaurant Price Index', 'Local Purchasing Power Index')
desviaciones_estandar <- sapply(datosReadr[, variables], sd)
# Mostrar las desviaciones estándar
print(desviaciones_estandar)
## Cost of Living Index Rent Index
## 16.14757 11.41227
## Cost of Living Plus Rent Index Groceries Index
## 13.26372 17.05511
## Restaurant Price Index Local Purchasing Power Index
## 18.25811 39.56909
medias <- sapply(datosReadr[, variables], mean)
coeficientes_variacion <- (desviaciones_estandar / medias) * 100
print(coeficientes_variacion)
## Cost of Living Index Rent Index
## 37.07367 71.09166
## Cost of Living Plus Rent Index Groceries Index
## 43.69124 38.56098
## Restaurant Price Index Local Purchasing Power Index
## 50.06189 60.78742
Además con la función Table() podemos analizar la frecuencia de los datos en cada variable:
table(datosReadr$`Local Purchasing Power Index`)
##
## 2.3 5.5 10.5 11 14.7 15.6 17.5 17.8 18.4 20 23.9 25.4 25.9
## 1 1 1 1 1 1 1 1 1 1 1 2 1
## 26 26.1 28.7 29.1 29.9 30.7 31.7 31.9 32.2 32.7 33.1 33.3 33.7
## 1 1 1 1 1 1 1 1 1 1 1 1 1
## 34.2 34.5 34.6 34.8 35.3 37.2 37.9 38.5 38.6 39.3 39.5 39.9 40.5
## 1 1 1 1 1 2 1 1 1 1 1 1 1
## 40.8 41.5 41.6 42 42.2 43.2 43.5 43.7 44.7 45.1 45.4 45.5 46.1
## 1 1 1 1 1 1 1 1 1 1 1 1 1
## 46.2 46.6 46.7 49 50.2 50.4 50.6 51 51.8 52.9 53 54.6 56.3
## 1 1 1 1 1 1 1 1 1 1 1 1 1
## 56.9 63.4 63.8 64.4 66.9 68 68.1 68.3 68.4 71.4 73.3 75 75.5
## 2 1 1 1 1 1 1 1 1 1 1 1 1
## 78.3 79.9 80.4 80.9 82.6 84 85.8 92.1 95.1 99.4 101.1 102.4 102.8
## 1 1 1 1 1 1 1 1 1 1 1 2 1
## 103.5 103.7 105 109.3 109.4 109.8 111.1 114.7 115.2 117 118 120.2 120.3
## 1 1 1 1 1 1 1 1 1 1 1 1 1
## 121 122.6 124.9 127.2 127.4 127.9 134.9 139.8 142.3 158.7 161.1 161.8 182.5
## 1 1 1 1 1 1 1 1 1 1 1 1 1
table(datosReadr$`Rent Index`)
##
## 2.4 2.8 3.5 3.7 3.8 4.3 4.7 5.6 5.8 6.1 6.2 6.5 7.1 7.2 7.4 7.5
## 1 1 1 2 1 1 1 2 1 1 1 1 1 1 1 1
## 7.6 7.7 7.8 7.9 8 8.3 8.4 8.5 8.6 8.7 9 9.1 9.6 9.9 10 10.1
## 3 4 1 1 1 1 1 2 2 1 1 1 2 1 3 1
## 10.2 10.3 10.6 10.7 11.1 11.2 11.3 11.5 11.8 12.2 12.3 12.4 12.6 12.9 13.1 13.2
## 1 1 2 1 1 3 2 1 1 1 2 1 1 1 2 1
## 13.4 13.7 13.8 14.1 14.6 14.8 15 15.3 15.5 15.6 15.8 16 16.7 16.9 17.1 18.7
## 2 1 2 1 1 1 1 1 1 1 1 1 1 1 1 1
## 18.8 19 19.2 19.5 19.7 20.1 20.5 20.9 21 22.1 22.5 22.6 22.9 24 24.2 24.4
## 1 2 1 1 1 2 1 1 1 1 1 1 1 1 1 1
## 24.8 25.9 26.2 26.4 27.1 31.1 33.2 33.4 33.5 36.1 36.7 39.2 40.5 41.3 41.7 42.3
## 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
## 46.5 59.4 67.2
## 1 1 1
table(datosReadr$`Groceries Index`)
##
## 17.5 21.2 22 22.2 23.8 24 24.1 24.5 25.4 25.6 25.7 27 28.2
## 1 1 1 1 1 1 1 1 3 1 1 1 2
## 28.4 28.8 29 29.3 29.4 29.5 29.7 29.8 30 30.3 31 31.4 31.5
## 1 1 1 1 1 1 2 1 1 1 1 1 1
## 31.6 32.1 32.2 33.3 33.4 33.9 34.5 34.6 34.9 35 35.5 36 36.3
## 1 1 2 1 1 2 2 1 1 1 1 2 1
## 36.6 36.7 36.8 37.1 37.5 37.6 38.2 39.5 39.8 39.9 40.5 40.7 41.6
## 1 1 3 1 1 2 1 1 1 1 1 2 2
## 41.8 42 42.8 43 43.4 43.5 43.7 43.8 43.9 44.2 44.4 45.3 46
## 1 1 1 1 2 2 1 1 1 1 1 1 1
## 46.4 46.7 46.9 48.3 48.4 49 49.3 49.6 50.6 52.1 53.7 55.3 56.1
## 1 1 1 1 1 1 1 1 1 1 1 1 1
## 56.9 57 57.5 59.3 59.6 59.9 60.1 60.8 62 63 64.1 64.8 66.4
## 1 1 1 1 1 1 1 2 1 1 2 1 1
## 69.5 71.2 71.9 74.6 75 77.3 79 80.8 81.4 81.6 84.6 88.4 109.1
## 1 1 1 1 1 1 1 1 1 1 1 1 1
Tambien conviene analizar los valores que se encuentran en el encabezado y la cola de la base de datos, ya que podemos determinar los paises con mayor y menor indice de costo de vida respectivamente:
#Cabeza
head(datosReadr[,c(1,2,3,8)])
## # A tibble: 6 × 4
## Rank Country `Cost of Living Index` `Local Purchasing Power Index`
## <dbl> <chr> <dbl> <dbl>
## 1 1 Switzerland 101. 159.
## 2 2 Bahamas 85 54.6
## 3 3 Iceland 83 120.
## 4 4 Singapore 76.7 111.
## 5 5 Barbados 76.6 43.5
## 6 6 Norway 76 115.
#Cola
tail(datosReadr[,c(1,2,3,8)])
## # A tibble: 6 × 4
## Rank Country `Cost of Living Index` `Local Purchasing Power Index`
## <dbl> <chr> <dbl> <dbl>
## 1 116 Tanzania 23.8 25.9
## 2 117 Bangladesh 22.5 33.1
## 3 118 India 21.2 82.6
## 4 119 Egypt 21 20
## 5 120 Libya 20.4 42
## 6 121 Pakistan 18.8 29.1
Es notable como la mayoría de paises que se encuentran en el fondo del ranking forman parte de Africa o de Asia Occidental, zonas caracterizadas por un alto indice de pobreza y varios conflictos armados.
Sin embargo, todavía existen valores de interes que podemos identificar de forma más sencilla a través de filtros, por ejemplo, que tal si queremos averiguar los 5 países con mayor indice de poder adquisitivo:
datosReadr2 <- datosReadr %>%
rename(cost_index = `Local Purchasing Power Index`)
resultado <- datosReadr2 %>%
arrange(desc(cost_index))
resultado[1:8,c(1,2,3,8)]
## # A tibble: 8 × 4
## Rank Country `Cost of Living Index` cost_index
## <dbl> <chr> <dbl> <dbl>
## 1 20 Luxembourg 62.4 182.
## 2 52 Kuwait 42.1 162.
## 3 37 Qatar 51.3 161.
## 4 1 Switzerland 101. 159.
## 5 9 United States 70.4 142.
## 6 51 Oman 42.4 140.
## 7 48 Saudi Arabia 45.3 135.
## 8 27 United Arab Emirates 55.8 128.
Con ayuda de este filtro podemos identificar rapidamente que el poder adquisitivo y el indice de costo de vida no van de la mano, ya que hay paises como Kuwait que tiene un alto poder adquisitivo pero ocupa el puesto 52 en el ranking, además se puede notar que varios paises de oriente medio y la peninsula arabiga tienen un gran poder adquisitivo. Podemos aplicar varios otros filtros:
filtro1 <- datosReadr %>% filter(`Local Purchasing Power Index`< 30)
print(filtro1[,c(1,2,3,8)])
## # A tibble: 19 × 4
## Rank Country `Cost of Living Index` Local Purchasing Power Inde…¹
## <dbl> <chr> <dbl> <dbl>
## 1 43 Cuba 46.7 2.3
## 2 54 Lebanon 41.8 25.4
## 3 65 Venezuela 38.3 14.7
## 4 67 Dominican Republic 37.9 28.7
## 5 71 Cambodia 37.3 23.9
## 6 72 Cameroon 37.3 10.5
## 7 73 Zimbabwe 37.2 26.1
## 8 77 Sri Lanka 34.6 17.5
## 9 86 Nigeria 31.4 11
## 10 90 Ghana 30.9 18.4
## 11 100 Uganda 29.1 17.8
## 12 101 Algeria 28.9 29.9
## 13 108 Iran 26.4 26
## 14 112 Nepal 25.5 25.4
## 15 114 Madagascar 24.5 15.6
## 16 115 Syria 24 5.5
## 17 116 Tanzania 23.8 25.9
## 18 119 Egypt 21 20
## 19 121 Pakistan 18.8 29.1
## # ℹ abbreviated name: ¹`Local Purchasing Power Index`
Es evidente como los paises con bajo poder adquisitivo forman parte de africa y asia occidental, a excepción de algunos paises como Venezuela, Republica dominicana y Cuba, este ultimo que resalta por tener proporcionalmente la mayor diferencia entre indice de costo de vida y poder adquisitivo.
filtro2 <- datosReadr %>% filter(`Rent Index` > 30 & `Rent Index` < 60)
print(filtro2[,c(1,2,3,4)])
## # A tibble: 13 × 4
## Rank Country `Cost of Living Index` `Rent Index`
## <dbl> <chr> <dbl> <dbl>
## 1 1 Switzerland 101. 46.5
## 2 2 Bahamas 85 36.7
## 3 3 Iceland 83 39.2
## 4 8 Hong Kong (China) 70.8 59.4
## 5 9 United States 70.4 41.7
## 6 10 Australia 70.2 33.4
## 7 12 Canada 64.8 33.2
## 8 14 Ireland 64.4 42.3
## 9 18 Netherlands 63.1 33.5
## 10 20 Luxembourg 62.4 40.5
## 11 22 United Kingdom 62 31.1
## 12 27 United Arab Emirates 55.8 41.3
## 13 37 Qatar 51.3 36.1
filtro3 <- datosReadr %>% filter(`Restaurant Price Index` > 36.47)
print(filtro3[,c(1,2,3,7)])
## # A tibble: 47 × 4
## Rank Country `Cost of Living Index` `Restaurant Price Index`
## <dbl> <chr> <dbl> <dbl>
## 1 1 Switzerland 101. 97
## 2 2 Bahamas 85 83.3
## 3 3 Iceland 83 86.8
## 4 4 Singapore 76.7 50.4
## 5 5 Barbados 76.6 69.4
## 6 6 Norway 76 73.5
## 7 7 Denmark 72.3 81.3
## 8 8 Hong Kong (China) 70.8 46.2
## 9 9 United States 70.4 67.2
## 10 10 Australia 70.2 62.5
## # ℹ 37 more rows
filtro4 <- datosReadr %>% filter(`Groceries Index` < 31.60)
print(filtro4[,c(1,2,3,6)])
## # A tibble: 30 × 4
## Rank Country `Cost of Living Index` `Groceries Index`
## <dbl> <chr> <dbl> <dbl>
## 1 78 South Africa 34.5 29.7
## 2 87 Azerbaijan 31.2 29
## 3 89 Russia 31 28.8
## 4 91 Brazil 30.2 29.5
## 5 92 Kenya 30.2 31
## 6 93 Botswana 30.1 30
## 7 95 Peru 30 31.5
## 8 96 Morocco 29.5 29.8
## 9 97 Kosovo (Disputed Territory) 29.5 29.4
## 10 98 Argentina 29.4 29.7
## # ℹ 20 more rows
filtro5 <- datosReadr %>% filter(`Local Purchasing Power Index` > 50 & `Rent Index` > 50)
print(filtro5[,c(1,2,3,4,8)])
## # A tibble: 2 × 5
## Rank Country `Cost of Living Index` `Rent Index` Local Purchasing Pow…¹
## <dbl> <chr> <dbl> <dbl> <dbl>
## 1 4 Singapore 76.7 67.2 111.
## 2 8 Hong Kong (C… 70.8 59.4 109.
## # ℹ abbreviated name: ¹`Local Purchasing Power Index`
Es necesario determinar si existen valores NA que puedan complicar la aplicacion de funciones o interpretacion de la base de datos, un rápido diagnostico que nos permite saber los valores NA y donde pueden ser encontrados, puede realizarse a través del ‘Missingness Map’ o Mapa de valores faltantes:
suppressWarnings(missmap(datosReadr))
Utilizando la función missmap() del paquete ‘Amelia’ se puede generar este gráfico que nos muestra en porcentajes los valores NA, para fortuna del analisis, no existe ningún valor NA en la base de datos ya que el 100% de los datos pueden ser observados.
Ahora utilizaremos graficas de cajas y bigotes con cada variable para describir su comportamiento e identificar los datos atipicos:
variables <- c("Cost of Living Index", "Rent Index", "Cost of Living Plus Rent Index", "Groceries Index", "Restaurant Price Index", "Local Purchasing Power Index")
for (var in variables) {
boxplot(datosReadr[[var]], main = var, ylab = var)
atipicos <- boxplot.stats(datosReadr[[var]])$out
if (length(atipicos) > 0) {
text(x = rep(1, length(atipicos)), y = atipicos, labels = round(atipicos, 2), pos = 4, col = "purple")
}
}
Encontrados los datos atipicos, se realizara una prueba de normalidad para describir la distribución de los datos, para eso usaremos la prueba Shapiro-Wilk con cada una de las varibales númericas:
numeric_vars <- datosReadr[sapply(datosReadr, is.numeric)]
normality_tests <- lapply(numeric_vars, shapiro.test)
print(normality_tests)
## $Rank
##
## Shapiro-Wilk normality test
##
## data: X[[i]]
## W = 0.95465, p-value = 0.0004534
##
##
## $`Cost of Living Index`
##
## Shapiro-Wilk normality test
##
## data: X[[i]]
## W = 0.93519, p-value = 1.906e-05
##
##
## $`Rent Index`
##
## Shapiro-Wilk normality test
##
## data: X[[i]]
## W = 0.82432, p-value = 1.052e-10
##
##
## $`Cost of Living Plus Rent Index`
##
## Shapiro-Wilk normality test
##
## data: X[[i]]
## W = 0.91147, p-value = 7.265e-07
##
##
## $`Groceries Index`
##
## Shapiro-Wilk normality test
##
## data: X[[i]]
## W = 0.91492, p-value = 1.132e-06
##
##
## $`Restaurant Price Index`
##
## Shapiro-Wilk normality test
##
## data: X[[i]]
## W = 0.9215, p-value = 2.71e-06
##
##
## $`Local Purchasing Power Index`
##
## Shapiro-Wilk normality test
##
## data: X[[i]]
## W = 0.92482, p-value = 4.273e-06
También se puede identificar la distribución de una variable a través de un histograma con Curva de densidad para la variable:
variables <- c('Cost of Living Index', 'Rent Index', 'Cost of Living Plus Rent Index', 'Groceries Index', 'Restaurant Price Index', 'Local Purchasing Power Index')
for (var in variables) {
p <- ggplot(datosReadr, aes(x = datosReadr[[var]])) +
geom_histogram(aes(y = ..density..), bins = 30, fill = "lightblue", color = "black") +
geom_density(color = "red", size = 1) +
labs(title = paste("Histograma con Curva de Densidad para", var),
x = var,
y = "Densidad") +
theme_minimal()
print(p) # Asegúrate de que 'p' es lo que se imprime
}
## 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.
## Warning: The dot-dot notation (`..density..`) was deprecated in ggplot2 3.4.0.
## ℹ Please use `after_stat(density)` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
Con esta representación se confirma que ninguna de las variables dentro de la base de datos sigue una distibución Normal, el histograma no es simetrico, además de que existen muchos valores que se alejan de la media.