Proceso de jerarquía analítica para datos de encuestas
enR
Posteriormente, cargamos los datos necesarios,
city200que consisten en datos generados aleatoriamente de
200 individuos en función de los pesos proporcionados en Saaty (2004) .
La metodología de generación de datos se explica al final de esta
viñeta. (———. 2004. "Toma de decisiones: la jerarquía analítica y los
procesos de red (Ahp/Anp)". Revista de ciencia de sistemas e
ingeniería de sistemas 13 (1): 1–35. https://doi.org/10.1007/s11518-006-0151-5 .)
library(magrittr)
## Warning: package 'magrittr' was built under R version 4.2.2
library(dplyr)
## Warning: package 'dplyr' was built under R version 4.2.2
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
library(Rdpack)
## Warning: package 'Rdpack' was built under R version 4.2.2
library(randomNames)
## Warning: package 'randomNames' was built under R version 4.2.2
library(rbibutils)
## Warning: package 'rbibutils' was built under R version 4.2.2
library(ahpsurvey)
atts <- c("cult", "fam", "house", "jobs", "trans")
data(city200)
head(city200)
## cult_fam cult_house cult_jobs cult_trans fam_house fam_jobs fam_trans
## 1 2 -2 2 -6 -4 -4 -8
## 2 2 -4 1 -4 -4 -2 -8
## 3 4 -2 1 -3 -7 -3 -5
## 4 8 -4 3 -4 -8 1 -7
## 5 3 -3 5 -6 -8 1 -4
## 6 6 -4 2 -4 -7 -2 -4
## house_jobs house_trans jobs_trans
## 1 4 -3 -8
## 2 4 -3 -7
## 3 4 -3 -6
## 4 4 -3 -9
## 5 4 -3 -6
## 6 4 -3 -6
library(magrittr)
library(dplyr)
library(Rdpack)
library(randomNames)
library(rbibutils)
library(ahpsurvey)
city200%>%
ahp.mat(atts = atts, negconvert = TRUE) %>%
head(3)
## [[1]]
## cult fam house jobs trans
## cult 1.0000000 0.500 2.0000000 0.500 6
## fam 2.0000000 1.000 4.0000000 4.000 8
## house 0.5000000 0.250 1.0000000 0.250 3
## jobs 2.0000000 0.250 4.0000000 1.000 8
## trans 0.1666667 0.125 0.3333333 0.125 1
##
## [[2]]
## cult fam house jobs trans
## cult 1.00 0.500 4.0000000 1.0000000 4
## fam 2.00 1.000 4.0000000 2.0000000 8
## house 0.25 0.250 1.0000000 0.2500000 3
## jobs 1.00 0.500 4.0000000 1.0000000 7
## trans 0.25 0.125 0.3333333 0.1428571 1
##
## [[3]]
## cult fam house jobs trans
## cult 1.0000000 0.2500000 2.0000000 1.0000000 3
## fam 4.0000000 1.0000000 7.0000000 3.0000000 5
## house 0.5000000 0.1428571 1.0000000 0.2500000 3
## jobs 1.0000000 0.3333333 4.0000000 1.0000000 6
## trans 0.3333333 0.2000000 0.3333333 0.1666667 1
El código a presentar realiza un análisis de proceso analítico jerárquico de una matriz de decisión llamada “city200” en R
En primer lugar, se realiza el análisis AHP utilizando la función ahp.mat del paquete ahp, que tomo como matriz de decisión a city200 y el vector atts de nombres de la columna como argumentos.
Negconver=T, para convertir los valores negativos en positivos en la matriz.
Se calculan las preferencias indivuales utilizando los métodos eigen y arithmetic con las funciones ahp.indpref. Los resultados de los métodos se comparaan para calcular el eror utilizando la diferencia máxima entre las dos matrices utilizando la función apply
library(ggplot2)
## Warning: package 'ggplot2' was built under R version 4.2.2
#Diferencia máxima de entre valor propio y agregación media
cityahp<-city200%>%ahp.mat(atts,negconvert = T)
eigentrue<-ahp.indpref(cityahp,atts,method = "eigen")
geom<-ahp.indpref(cityahp,atts,method ="arithmetic" )
error<-data.frame(id=1:length(cityahp), maxdiff=apply(abs(eigentrue-geom),1,max))
error%>%
ggplot(aes(x = id, y = maxdiff)) +
geom_point() +
geom_hline(yintercept = 0.05, linetype = "dashed", color = "red") +
geom_hline(yintercept = 0, color = "gray50") +
scale_x_continuous("Respondent ID") +
scale_y_continuous("Maximum difference") +
theme_minimal()
Interpretación:
La linea roja indica un umbral de diferencia máximo aceptable (0.05) y la distancia entte los resultados de los métodos está por encima del umbral significa que es signnifiativo.
Se considera que existe diferencia signnificativa entre los resultados obtennidos con ambos métodos.
El código ha mostrar calcula la matriz de preferencias agregadas utilizando el método de agregación aritmética. La matriz de preferencias agregadas es una matriz que resume las preferencias de todos los evaluadores en una sola matriz. Esto se hace para poder obtener un ranking de las alternativas evaluadas, lo que facilita la toma de decisiones.
amean<-ahp.aggpref(cityahp,atts, method = "arithmetic")
amean
## cult fam house jobs trans
## 0.16200828 0.43673193 0.07607178 0.28274933 0.04243868
library(ggplot2)
library(tidyr)
##
## Attaching package: 'tidyr'
## The following object is masked from 'package:magrittr':
##
## extract
#se crea una matriz vacía con 50 filas y 5 columnas para almacenar los resultados de los pesos de los criterios.
qtresults <- matrix(nrow = 50, ncol = 5, data = NA)
for (q in 1:50){
qtresults[q,] <- ahp.aggpref(cityahp, atts, method = "arithmetic",
aggmethod = "tmean", qt = (q-1)/100)
}
colnames(qtresults) <- atts
qtresults %>%
as.data.frame() %>%
mutate(trimperc = 1:nrow(qtresults)-1) %>%
mutate(cult = cult - amean[1],
fam = fam - amean[2],
house = house - amean[3],
jobs = jobs - amean[4],
trans = trans - amean[5]) %>%
gather(cult, fam, house, jobs, trans, key = "att", value = "weight") %>%
ggplot(aes(x = trimperc, y = weight, group = att, shape = att, color = att, fill = att)) +
geom_line() +
geom_point() +
scale_x_continuous("el percentil superior e inferior recortado") +
scale_y_continuous("el cambio del promedio no recortado") +
geom_hline(yintercept = 0, color = "gray") +
theme_minimal()
Cambios de ponderaciones agregadas en función del cuantil de datos recortados
library(knitr)
mean <- city200 %>%
ahp.mat(atts = atts, negconvert = TRUE) %>%
ahp.aggpref(atts, method = "arithmetic")
sd <- city200 %>%
ahp.mat(atts = atts, negconvert = TRUE) %>%
ahp.aggpref(atts, method = "arithmetic", aggmethod = "sd")
t(data.frame(mean, sd))%>% kable()
| cult | fam | house | jobs | trans | |
|---|---|---|---|---|---|
| mean | 0.1620083 | 0.4367319 | 0.0760718 | 0.2827493 | 0.0424387 |
| sd | 0.0333849 | 0.0544975 | 0.0088232 | 0.0482966 | 0.0074665 |
city200 %>%
ahp.mat(atts = atts, negconvert = TRUE) %>%
ahp.aggjudge(atts, aggmethod = "geometric")
## cult fam house jobs trans
## cult 1.0000000 0.2202027 3.0925191 0.4882218 4.638350
## fam 4.5412708 1.0000000 6.4612364 1.7035125 6.145824
## house 0.3233610 0.1547691 1.0000000 0.2488201 2.926539
## jobs 2.0482496 0.5870224 4.0189678 1.0000000 7.039173
## trans 0.2155939 0.1627121 0.3417005 0.1420621 1.000000
weight<-c(5,-3,-2,-5,7,-1,-7,4,-3,-7)
sample_mat<-ahp.mat(t(weight),atts,negconvert = TRUE)
(cr_Std<-ahp.cr(sample_mat,atts ))
## [1] 0.6331181
Indicaría que la matriz de comparación de pesos no es completamente consistente. La AHP considera que una matriz es consistente si el CI es menor o igual a 0.1. Por lo tanto, en este caso, un valor de 0.63, sugiere que la matriz de comparación de pesos puede requerir ajustes o correcciones para ser completamente consistente.
cr<-city200%>%ahp.mat(atts,negconvert = T)%>%ahp.cr(atts)
table(cr<=0.1)
##
## FALSE TRUE
## 70 130
Esta salida significa que de todas las comparaciones en la matriz de
pesos city200, hay 70 comparaciones que
tienen un índice de consistencia mayor que 0.1 (es decir, se consideran
consistentes) y hay 130 comparaciones que tienen un índice de
consistencia menor o igual a 0.1 (es decir, se consideran inconsistente)
Evaluar la consistencia del análisis jeráquico de procesos con 5
dimensiones utilizando 1000 simulaciones. R valor del indice RI se basa
en una distribución aletaoria y se utilizará como referencia para
comparra el índice de consistencia obtenido en la matriz de comparación
de pesos.
## Genere un índice aleatorio con 1000 simulaciones, 5 dimensiones y semilla 30000 para reproducibilidad (semilla = 42 por defecto).
(RI<-ahp.ri(nsims = 1000, dim=5, seed = 30000))
## [1] 1.115356
## Use este RI para calcular el índice de consistencia en lugar del predeterminado.
ahp.cr(sample_mat, atts, RI)
## [1] 0.6290004
thres <- 0.1
dict <- c("cult" = "Culture",
"fam" = "Family",
"house" = "Housing",
"jobs" = "Jobs",
"trans" = "Transportation")
cr.df <- city200 %>%
ahp.mat(atts, negconvert = TRUE) %>%
ahp.cr(atts) %>%
data.frame() %>%
mutate(rowid = 1:length(cr), cr.dum = as.factor(ifelse(cr <= thres, 1, 0))) %>%
select(cr.dum, rowid)
city200 %>%
ahp.mat(atts = atts, negconvert = TRUE) %>%
ahp.indpref(atts, method = "eigen") %>%
mutate(rowid = 1:nrow(eigentrue)) %>%
left_join(cr.df, by = 'rowid') %>%
gather(cult, fam, house, jobs, trans, key = "var", value = "pref") %>%
ggplot(aes(x = var, y = pref)) +
geom_violin(alpha = 0.6, width = 0.8, color = "transparent", fill = "gray") +
geom_jitter(alpha = 0.6, height = 0, width = 0.1, aes(color = cr.dum)) +
geom_boxplot(alpha = 0, width = 0.3, color = "#808080") +
scale_x_discrete("Attribute", label = dict) +
scale_y_continuous("Weight (dominant eigenvalue)",
labels = scales::percent,
breaks = c(seq(0,0.7,0.1))) +
guides(color=guide_legend(title=NULL))+
scale_color_discrete(breaks = c(0,1),
labels = c(paste("CR >", thres),
paste("CR <", thres))) +
labs(NULL, caption = paste("n =", nrow(city200), ",", "Mean CR =",
round(mean(cr),3)))+
theme_minimal()