El dataset tenía muchos problemas, como esta con comas, al pasar a tipo numerico los numeros o cambiaban completamente o se sustituian por NA, el porcentaje tp estaba en un formato incorrecto desde el momento de exportarlo
data = read.csv("espcalob.csv")
data1 = data.frame("variable" = colnames(data),
"tipo" = c(rep("categorical",3), rep("numerical", 10),
rep("categorical",2), rep("numerical",4)), stringsAsFactors = FALSE)
El siguiente código es una función para pasar las columnas al tipo de datos que especifico. Cuando es de tipo numerica se sustituyen las comas por los puntos, porque anteriormente solo las variables con valores de numeros redondos eran reconocidas como variables numericas.
## Pais Año Estatus Esperanza.de.vida
## Austria : 48 2000 : 78 Developed :1056 Min. :69.90
## Belgium : 48 2001 : 78 Developing: 192 1st Qu.:75.30
## Bulgaria: 48 2002 : 78 Median :78.50
## Croatia : 48 2003 : 78 Mean :78.45
## Cyprus : 48 2004 : 78 3rd Qu.:81.03
## Czechia : 48 2005 : 78 Max. :89.00
## (Other) :960 (Other):780
## Mortalidad.adulta Alcohol..L.año. Porcentaje.gastos IMC
## Min. : 1.00 Min. : 0.01 Min. : 0.0 Min. : 5.10
## 1st Qu.: 63.00 1st Qu.: 9.56 1st Qu.: 143.7 1st Qu.:54.90
## Median : 81.00 Median :10.98 Median : 703.0 Median :57.60
## Mean : 89.23 Mean :10.55 Mean : 2231.0 Mean :53.55
## 3rd Qu.:124.00 3rd Qu.:12.12 3rd Qu.: 3298.0 3rd Qu.:59.90
## Max. :229.00 Max. :17.87 Max. :18961.3 Max. :69.60
## NA's :78
## Gasto.total PIB Poblacion Delgadez.1.19.años.
## Min. : 1.100 Min. : 12.28 Min. : 123 Min. :0.300
## 1st Qu.: 6.320 1st Qu.: 3349.99 1st Qu.: 246354 1st Qu.:0.800
## Median : 7.535 Median : 12102.12 Median : 1468719 Median :1.200
## Mean : 7.250 Mean : 18208.58 Mean : 7826012 Mean :1.423
## 3rd Qu.: 8.920 3rd Qu.: 27019.43 3rd Qu.: 5759450 3rd Qu.:2.000
## Max. :11.970 Max. :119172.74 Max. :82534176 Max. :4.000
## NA's :78 NA's :96 NA's :96
## IDH Region Sexo Media.obes
## Min. :0.703 Europe:1248 Both sexes:416 Min. : 9.43
## 1st Qu.:0.805 Men :416 1st Qu.:15.56
## Median :0.844 Women :416 Median :18.42
## Mean :0.838 Mean :18.50
## 3rd Qu.:0.876 3rd Qu.:20.95
## Max. :0.926 Max. :32.88
## NA's :48
## Animal.kcal Total.kcal Vegetal.kcal
## Min. : 540.0 Min. :2556 Min. :1840
## 1st Qu.: 837.2 1st Qu.:3142 1st Qu.:2177
## Median : 929.5 Median :3342 Median :2350
## Mean : 955.9 Mean :3297 Mean :2341
## 3rd Qu.:1076.8 3rd Qu.:3505 3rd Qu.:2497
## Max. :1427.0 Max. :3804 Max. :2887
##
Hay 396 datos faltantes. Proceden de variables como Alchol, Gasto, PIB, Poblacion y IDH. De estos, solo nos interesa estudiar en general el IDH y como se relaciona con la obesidad y las calorias. Asi que los que no tienen IDH se eliminan. Ahora ya no hay NA.
cat("Total de valores faltantes en el conjunto de datos:", sum(is.na(data)), "\n")
## Total de valores faltantes en el conjunto de datos: 0
cat("Variables con valores faltantes:\n")
## Variables con valores faltantes:
print(colSums(is.na(data))[colSums(is.na(data)) > 0])
## named numeric(0)
168 filas se ven afectadas por los datos faltantes, pero solo interesan los respectivos al IDH.
print(data[!complete.cases(data), ])
## [1] Pais Año Estatus
## [4] Esperanza.de.vida Mortalidad.adulta Porcentaje.gastos
## [7] IMC Delgadez.1.19.años. IDH
## [10] Region Sexo Media.obes
## [13] Animal.kcal Total.kcal Vegetal.kcal
## <0 rows> (o 0- extensión row.names)
Se eliminan las filas sin el IDH, ya que nos centramos en estudiar la obesidad y las calorias en base a eso.
#ahora tiene 1200 observaciónes
dataset = data[!is.na(data$IDH), ]
# Boxplot de variables escaladas
datos_escalados <- dataset %>%
select(where(is.numeric)) %>%
scale() %>%
as.data.frame() %>%
pivot_longer(everything(), names_to = "variable", values_to = "valor")
ggplot(datos_escalados, aes(x = variable, y = valor)) +
geom_boxplot(fill = "lightblue", outlier.color = "red") +
labs(title = "Boxplots", x = "", y = "Valores") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
#Selecciono solo 2015 y de ambos sexos. Como hay datos para hombres, para mujeres y por años, concreto unos valores.
dataset2015 <- dataset %>%
filter(Sexo == "Both sexes", Año == 2015)
CON DATASET2015:
Cluster 1: Países con obesidad y dietas normales en calorías (dietas altas en calorías y obesidad, pero IDH no alto). Cluster 2: Corresponde a países desarrollados (alto IDH, buena alimentación, baja obesidad).
datos_numericos <- scale(dataset2015[, c("IDH", "Total.kcal", "Media.obes")])
set.seed(123)
kmeans_result <- kmeans(datos_numericos, centers = 2)
dataset2015$cluster_kmeans <- as.factor(kmeans_result$cluster)
ggplot(dataset2015, aes(x = Media.obes, y = IDH, color = cluster_kmeans)) +
geom_point() + theme_minimal()
kmeans_result$centers
## IDH Total.kcal Media.obes
## 1 -0.8053475 -0.4546968 0.6412679
## 2 0.8724598 0.4925882 -0.6947069
clusters_2015 <- dataset2015 %>%select(Pais, cluster_kmeans)
dataset <- dataset %>% left_join(clusters_2015, by = "Pais") # Asigna el cluster de 2015 a todos los años
#En dataset solo escojo los datos de ambos sexos
dataset <- dataset %>%
filter(Sexo == "Both sexes")
Ahora se realiza un gráfico para ver como han evolucionado los valores de los paises a lo largo de los años. Como hay varios paises, se estudiara según los clusters anteriores de cada pais, usando la media de obesidad por cluster y por año como valor a representar (k means).
ggplot(dataset, aes(
x = Año,
y = Media.obes,
color = as.factor(cluster_kmeans),
group = interaction(Pais, cluster_kmeans))) +
geom_line(alpha = 0.4) +geom_smooth(aes(group = cluster_kmeans), se = FALSE, linewidth = 1.5) +
labs(title = "Evolución del Media.obes por país", x = "Año",
y = "Media.obes", color = "Cluster") + scale_color_manual(values =
c("#1b9e77", "#7570b3"),labels = c("Cluster 1", "Cluster 2")) +theme_minimal()
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
ggplot(dataset, aes(
x = Año,
y = IDH,
color = as.factor(cluster_kmeans),
group = interaction(Pais, cluster_kmeans) )) +
geom_line(alpha = 0.4) +geom_smooth(aes(group = cluster_kmeans), se = FALSE, linewidth = 1.5) +
labs(title = "Evolución del IDH por país", x = "Año",
y = "IDH", color = "Cluster") + scale_color_manual(values =
c("#1b9e77","#7570b3"),labels = c("Cluster 1", "Cluster 2")) +theme_minimal()
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
ggplot(dataset, aes(
x = Año,
y = Total.kcal,
color = as.factor(cluster_kmeans),
group = interaction(Pais, cluster_kmeans))) +
geom_line(alpha = 0.4) +geom_smooth(aes(group = cluster_kmeans), se = FALSE, linewidth = 1.5) +
labs(title = "Evolución del Total.kcal por país", x = "Año",
y = "Total.kcal", color = "Cluster") + scale_color_manual(values =
c("#1b9e77", "#7570b3"),labels = c("Cluster 1", "Cluster 2")) +theme_minimal()
## `geom_smooth()` using method = 'loess' and formula = 'y ~ x'
cluster1_data <- dataset %>%
filter(cluster_kmeans == 1) %>% group_by(Año) %>%
summarise(Total = mean(Total.kcal, na.rm = TRUE), Animal = mean(Animal.kcal, na.rm = TRUE),
Vegetal = mean(Vegetal.kcal, na.rm = TRUE)) %>% tidyr::pivot_longer(cols = c(Total, Animal, Vegetal),
names_to = "Tipo", values_to = "kcal")
ggplot(cluster1_data, aes(x = Año, y = kcal, color = Tipo, linetype = Tipo)) +
geom_line(linewidth = 1.2) + geom_point(size = 3) +
scale_color_manual( values = c("Total" = "black", "Animal" = "#d90f09", "Vegetal" = "#1b9e77")) + scale_linetype_manual( values = c("Total" = "solid", "Animal" = "dashed", "Vegetal" = "dotted") ) +
labs( title = "Consumo Calórico en Cluster 1 (2000-2015)",
subtitle = "Total.kcal = Animal.kcal + Vegetal.kcal", y = "kcal per cápita/día", x = "Año" ) + theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
cluster1_data <- dataset %>%
filter(cluster_kmeans == 2) %>% group_by(Año) %>%
summarise(Total = mean(Total.kcal, na.rm = TRUE), Animal = mean(Animal.kcal, na.rm = TRUE),
Vegetal = mean(Vegetal.kcal, na.rm = TRUE)) %>% tidyr::pivot_longer(cols = c(Total, Animal, Vegetal),
names_to = "Tipo", values_to = "kcal")
ggplot(cluster1_data, aes(x = Año, y = kcal, color = Tipo, linetype = Tipo)) +
geom_line(linewidth = 1.2) + geom_point(size = 3) +
scale_color_manual( values = c("Total" = "black", "Animal" = "#d90f09", "Vegetal" = "#1b9e77")) + scale_linetype_manual( values = c("Total" = "solid", "Animal" = "dashed", "Vegetal" = "dotted") ) +
labs( title = "Consumo Calórico en Cluster 2 (2000-2015)",
subtitle = "Total.kcal = Animal.kcal + Vegetal.kcal", y = "kcal per cápita/día", x = "Año" ) + theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
#TESTS
Cual es el mejor metodo para estudiar la relación? Spearman
ggplot(dataset2015, aes(x = Media.obes, y = IDH, color = as.factor(cluster_kmeans))) +
geom_point(size = 3, alpha = 0.7) +
labs(title = "Asignación de Clusters: IDH vs Obesidad")
dist_mat <- dist(scale(dataset2015[, c("Media.obes", "IDH")]))
silhouette_score <- silhouette(as.numeric(dataset2015$cluster_kmeans), dist_mat)
summary(silhouette_score)
## Silhouette of 25 units in 2 clusters from silhouette.default(x = as.numeric(dataset2015$cluster_kmeans), dist = dist_mat) :
## Cluster sizes and average silhouette widths:
## 13 12
## 0.5029029 0.5224075
## Individual silhouette widths:
## Min. 1st Qu. Median Mean 3rd Qu. Max.
## 0.1045 0.4567 0.5645 0.5123 0.6083 0.6421
plot(silhouette_score)
#El coeficiente de silhouette no es muy alto, pero es mejor con 2 clusters que con 3 o 4
Correlación (r): -0.5138462 -> Relación negativa moderada. A mayor IDH, menor obesidad.
cor.test(dataset2015$IDH, dataset2015$Media.obes, method = "spearman")
##
## Spearman's rank correlation rho
##
## data: dataset2015$IDH and dataset2015$Media.obes
## S = 3936, p-value = 0.009439
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho
## -0.5138462
variables <- dataset[, c("Total.kcal", "Media.obes", "IDH", "Vegetal.kcal", "Animal.kcal")]
cor_pearson <- round(cor(variables, method = "pearson"), 2)
cor_spearman <- round(cor(variables, method = "spearman"), 2)
diff_matrix <- abs(cor_pearson - cor_spearman)
print(diff_matrix) #spearman es mejor porque hay relaciones no liniales, por eso es mas alto su valor
## Total.kcal Media.obes IDH Vegetal.kcal Animal.kcal
## Total.kcal 0.00 0.05 0.03 0.01 0.05
## Media.obes 0.05 0.00 0.06 0.02 0.03
## IDH 0.03 0.06 0.00 0.01 0.00
## Vegetal.kcal 0.01 0.02 0.01 0.00 0.01
## Animal.kcal 0.05 0.03 0.00 0.01 0.00
Estudio las relaciones con el dataset que contiene información sobre diversos años:
El consumo calórico total (Total.kcal) no está asociado significativamente con la obesidad A mayor Kcal, mayor IDH, pero su poca correlación es lineal.
cor_matrix <- cor(variables, method = "spearman")
corrplot(cor_matrix, method = "number")
cor.test(dataset2015$IDH, dataset2015$Media.obes, method = "spearman")
##
## Spearman's rank correlation rho
##
## data: dataset2015$IDH and dataset2015$Media.obes
## S = 3936, p-value = 0.009439
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho
## -0.5138462
cor.test(dataset2015$Total.kcal, dataset2015$Media.obes, method = "spearman")
##
## Spearman's rank correlation rho
##
## data: dataset2015$Total.kcal and dataset2015$Media.obes
## S = 2866, p-value = 0.6253
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho
## -0.1023077
cor.test(dataset2015$IDH, dataset2015$Total.kcal, method = "pearson")
##
## Pearson's product-moment correlation
##
## data: dataset2015$IDH and dataset2015$Total.kcal
## t = 3.0224, df = 23, p-value = 0.006062
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.1748815 0.7667649
## sample estimates:
## cor
## 0.5331698
cor.test(dataset2015$IDH, dataset2015$Animal.kcal, method = "pearson")
##
## Pearson's product-moment correlation
##
## data: dataset2015$IDH and dataset2015$Animal.kcal
## t = 3.5867, df = 23, p-value = 0.00156
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## 0.2669538 0.8038192
## sample estimates:
## cor
## 0.5989106
Significancia estadística (p=0.418): El consumo de calorías vegetales no está asociado significativamente con la obesidad en tu muestra.
Coeficiente de correlación (r=-0.312): A mayor consumo de calorías animales, menor obesidad, pero la asociación no es fuerte.
# Correlación entre obesidad y calorías vegetales
cor.test(dataset2015$Vegetal.kcal, dataset2015$Media.obes, method = "pearson")
##
## Pearson's product-moment correlation
##
## data: dataset2015$Vegetal.kcal and dataset2015$Media.obes
## t = 0.82428, df = 23, p-value = 0.4182
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## -0.2419330 0.5291078
## sample estimates:
## cor
## 0.1693909
# Correlación entre obesidad y calorías animales
cor.test(dataset2015$Animal.kcal, dataset2015$Media.obes, method = "pearson")
##
## Pearson's product-moment correlation
##
## data: dataset2015$Animal.kcal and dataset2015$Media.obes
## t = -1.5734, df = 23, p-value = 0.1293
## alternative hypothesis: true correlation is not equal to 0
## 95 percent confidence interval:
## -0.62934448 0.09511309
## sample estimates:
## cor
## -0.3117334
#REPRESENTACIONES
# Países de Europa a dibujar (no se tiene info de todos)
europe_countries <- c("Albania", "Austria", "Belgium", "Bulgaria", "Croatia", "Cyprus", "Czech Republic",
"Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary",
"Iceland", "Ireland", "Italy", "Latvia", "Lithuania", "Luxembourg", "Malta",
"Netherlands", "Norway", "Poland", "Portugal", "Romania", "Slovakia",
"Slovenia", "Spain", "Sweden", "Switzerland", "UK", "Turkey")
# Se cambian nombres para que coincidan con map_data("world")
dataset2015_europa <- dataset2015 %>%
mutate(
Pais = case_when(
Pais == "Czechia" ~ "Czech Republic",
Pais == "Russia" ~ "Russian Federation",
Pais == "United Kingdom" ~ "UK",
TRUE ~ Pais)) %>%
filter(Pais %in% europe_countries)
europe_map <- map_data("world") %>% filter(region %in% europe_countries)
europe_data <- europe_map %>%
left_join(dataset2015_europa, by = c("region" = "Pais"))
ggplot(europe_data, aes(x = long, y = lat, group = group, fill = Media.obes)) +
geom_polygon(color = "white", size = 0.2) +
scale_fill_gradient(
name = "Obesidad (%)",
low = "#f7fcb9",
high = "#d95f0e",
na.value = "gray80") +
labs(
title = "Prevalencia de Obesidad en Europa (2015)",
subtitle = "Datos para ambos sexos",
caption = "Fuente: FAO/OMS") +
theme_void() +
theme(plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
legend.position = "right", legend.title = element_text(size = 10)) + coord_fixed(1.3)
## 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.
paises_europa <- c(
"Albania", "Austria", "Belgium", "Bulgaria", "Croatia", "Cyprus", "Czech Republic",
"Denmark", "Estonia", "Finland", "France", "Germany", "Greece", "Hungary",
"Iceland", "Ireland", "Italy", "Latvia", "Lithuania", "Luxembourg", "Malta",
"Netherlands", "Norway", "Poland", "Portugal", "Romania", "Slovakia",
"Slovenia", "Spain", "Sweden", "Switzerland", "UK", "Turkey")
dataset_europe <- dataset %>%
mutate(
Pais = case_when(
Pais == "Czechia" ~ "Czech Republic",
Pais == "Russia" ~ "Russian Federation",
TRUE ~ Pais ) ) %>%
filter(Pais %in% paises_europa)
europe_map <- map_data("world") %>%
filter(region %in% paises_europa)
europe_clusters <- europe_map %>%
left_join(dataset_europe %>% distinct(Pais, cluster_kmeans),
by = c("region" = "Pais"))
ggplot(europe_clusters, aes(x = long, y = lat, group = group, fill = factor(cluster_kmeans))) +
geom_polygon(color = "white", size = 0.2) + scale_fill_manual( name = "Cluster",
values = c("1" = "#4e79a7", "2" = "#e15759"),
labels = c("Cluster 1", "Cluster 2"),
na.value = "gray90") +labs( title = "Países de Europa por Cluster",
caption = "Clusters basados en IDH, Calorías y Obesidad") +
theme_void() + theme( plot.title = element_text(hjust = 0.5, face = "bold", size = 14),
legend.position = "right") + coord_fixed(1.3)
Finalmente se va crear un modelo para predecir el IDH en base a las
variables que más relación tienen con él. Usando Esperanza.de.vida,
Mortalidad.adulta, Delgadez.1.19.años., Media.obes y Animal.kcal.
datos_modelo <- dataset[, c("IDH", "Esperanza.de.vida", "Mortalidad.adulta", "Delgadez.1.19.años.", "Animal.kcal")]
cor_matrix <- cor(datos_modelo, method = "spearman")
round(cor_matrix, 2)
## IDH Esperanza.de.vida Mortalidad.adulta
## IDH 1.00 0.75 -0.42
## Esperanza.de.vida 0.75 1.00 -0.54
## Mortalidad.adulta -0.42 -0.54 1.00
## Delgadez.1.19.años. -0.50 -0.70 0.50
## Animal.kcal 0.66 0.41 -0.19
## Delgadez.1.19.años. Animal.kcal
## IDH -0.50 0.66
## Esperanza.de.vida -0.70 0.41
## Mortalidad.adulta 0.50 -0.19
## Delgadez.1.19.años. 1.00 -0.35
## Animal.kcal -0.35 1.00
corrplot(cor_matrix, method = "number", type = "upper", mar = c(0, 0, 1, 0))
set.seed(123)
sample <- sample(c(TRUE, FALSE), nrow(datos_modelo), replace = TRUE, prob = c(0.8, 0.2))
train <- datos_modelo[sample, ]
test <- datos_modelo[!sample, ]
modelo <- lm(IDH ~ Esperanza.de.vida + Delgadez.1.19.años. +I(Esperanza.de.vida^2)+ Animal.kcal, data = train) #quito mortalidad
summary(modelo)
##
## Call:
## lm(formula = IDH ~ Esperanza.de.vida + Delgadez.1.19.años. +
## I(Esperanza.de.vida^2) + Animal.kcal, data = train)
##
## Residuals:
## Min 1Q Median 3Q Max
## -0.098758 -0.015570 0.003588 0.019793 0.051760
##
## Coefficients:
## Estimate Std. Error t value Pr(>|t|)
## (Intercept) -1.763e+00 4.938e-01 -3.571 0.00041 ***
## Esperanza.de.vida 5.740e-02 1.225e-02 4.686 4.13e-06 ***
## Delgadez.1.19.años. -2.800e-03 3.019e-03 -0.927 0.35444
## I(Esperanza.de.vida^2) -3.241e-04 7.592e-05 -4.270 2.58e-05 ***
## Animal.kcal 1.058e-04 9.479e-06 11.167 < 2e-16 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## Residual standard error: 0.02664 on 320 degrees of freedom
## Multiple R-squared: 0.7005, Adjusted R-squared: 0.6967
## F-statistic: 187.1 on 4 and 320 DF, p-value: < 2.2e-16
predecir <- predict(modelo, newdata = test)
PRESS <- sum((test$IDH - predecir)^2)
TSS <- sum((test$IDH - mean(train$IDH))^2)
Q2 <- 1 - (PRESS / TSS)
print(paste("Q2(bondad de predicción):", round(Q2, 3))) #Predice bien los datos, 64%
## [1] "Q2(bondad de predicción): 0.645"
RMSE <- sqrt(mean((test$IDH - predecir)^2))
print(paste("RMSE:", round(RMSE, 3)))
## [1] "RMSE: 0.025"
dataset$IDH_predicho <- predict(modelo, newdata = dataset)
El modelo predice con poco error (0.025 respecto al IDH real) los valores de IDH R-squared: 0.6834, significa que el 70% de la varianza esta explicada por el resto de variables. Quitar obesidad