Çok Kriterli Karar Verme Yöntemleri ile Yaşanacak İl Seçimi

Decision Making

Yaşam endeksi verileri ve TOPSIS yöntemi kullanılarak illerin sıralanması.

A. Uraz Akgül
2022-06-19

Yaşayacağımız yere karar verme süreci içerisinde olduğumuzu ve bunu da çok kriterli karar verme yöntemleri ile yapmak istediğimizi varsayalım. Böyle bir süreç ve düşüncenin içinde en uygun kararı verebilmek için bir veri setine ihtiyacımız olacak. Bu veri setini TÜİK’ten alacağız. TÜİK, 2016 yılında İllerde Yaşam Endeksi, 2015 başlıklı bir çalışma paylaşmıştı ve en yüksek endeks değerini Isparta almıştı. Çalışmaya konu endeks, yaşamın 11 boyutunu 41 gösterge ile temsil eden bir bileşik endekstir.

Biz karar verme sürecimizde bu 41 göstergeyi kullanmak zorunda değiliz. Hatta ağırlıkları da önem derecemize göre değiştirebiliriz.

Uygulamanın bundan sonraki kısmında subjektif değerlendirmelerim ile devam edeceğim için sizler göstergeleri ve ağırlıkları değiştirebilirsiniz.

11 boyut ve 41 gösterge içerisinden seçmiş olduğum boyut ve göstergeler aşağıdadır. Listeye aynı zamanda ilgili göstergenin pozitif ve negatif bilgisini ve ileride ihtiyacımız olacak ağırlıkları (toplamları 1 olacak) da ekledim.

11 boyutu 9’a, 41 göstergeyi 20’ye düşürmüş oldum. Verilere (post13.xls) GitHub hesabımdan ulaşabilirsiniz. Eğer TÜİK üzerinden veri setine ulaşmak isterseniz Gelir, Yaşam, Tüketim ve Yoksulluk kategorisine girdikten sonra İllerde Yaşam Endeksi alt kategorisini filtreleyip İstatistiksel Tablolar bölümünden indirebilirsiniz. Hedef dosya: İllerde Yaşam Endeksi Gösterge Değerleridir.

Aşağıda örnek olması açısından İstanbul ve Muğla’ya ait gösterge değerleri verilmiştir.

indicators İstanbul Muğla
konut_kalite 15.95000 17.56500
issizlik 11.20000 7.30000
saglik_hizmet 67.43000 71.48000
okul_oncesi 27.51277 38.33912
egitim_hizmet 61.59000 66.79000
pm10_istasyon 54.80000 81.00000
orman_alan 43.99341 66.48696
sokak_gurultu 33.75000 17.19000
temizlik_hizmet 80.69000 70.08000
cinayet_oran 22.53597 52.54279
gece_yalniz 45.10000 63.82000
asayis_hizmet 68.51000 79.77000
internet_abone 17.62955 14.49276
kanalizasyon_sebeke 100.00000 83.00000
havalimani_erisim 9874.83432 318.22520
toplu_tasima_hizmet 69.89000 53.33000
sinema_tiyatro 147.44083 56.06305
avm_alani 277.27405 175.16313
sosyal_hayat 51.41000 52.05000
mutluluk 58.40000 52.40000

Technique for Order Preference by Similarity to Ideal Solution’ın kısaltması ve çok kriterli karar verme yöntemlerinden biri olan TOPSIS, İdeal Çözüme Dayalı Sıralama Tekniği olarak çevrilebilir. TOPSIS’in gizemli mantığı, seçilen alternatifin en iyi çözümden en kısa geometrik uzaklığa ve en kötü çözümden en uzun geometrik uzaklığa sahip olması gerektiği kavramına dayanmaktadır.

TOPSIS yönteminin hem adımlarına bakalım hem de bu adımları uygulayalım.

Adım 0) Veri seti: 81 ilin 9 boyut ve 20 göstergede değerleri

library(readxl)
library(tidyverse)

endeks <- read_excel("yasam_endeksi.xls")

Adım 1) Karar matrisinin yaratılması

Karar matrisinin satırları alternatiflerden (iller), sütunları kriterlerden (göstergeler) oluşmaktadır.

Alternatifler M, kriterler N olsun. Karar matrisi:

\((a_{ij})_{MxN}\)

il <- endeks$il # kullanmak için il sütunu ayrıldı
m <- as.matrix(endeks[,-1]) # matris oluşturuldu

Adım 2) Karar Matrisinin Normalize Edilmesi

\(a_{ij} = \frac{a_{ij}}{\sqrt{\sum_{i=1}^{M}(a_{ij}^2)}}\)

m_denominator <- apply(m, 2, function(x) sqrt(sum(x**2))) # payda burada hesaplandı
m2 <- m # m matrisi haricinde ikinci bir matris oluşturuldu

for(col in 1:ncol(m2)){
  
  for(row in 1:nrow(m2)){
    
    m2[row,col] <- m2[row,col] / m_denominator[col]
    
  }
  
}

Örnek: konut_kalite sütunundaki ilk değer 22.73’tür. 22.73’ü ilgili sütunda yer alan değerlerin karelerinin toplamının kareköküne bölüyoruz. Bu değer ise 203.314’tür. Sonuç olarak 22.73/203.314 = 0.1117975’tir.

Adım 3) Ağırlıklı Normalleştirilmiş Karar Matrisinin Oluşturulması

\(x_{ij} = a_{ij} * w_j\)

\(w_j = \frac{w_j}{\sum_{j=1}^{N}w_j}\)

\(\sum_{j=1}^{N}w_j = 1\)

Göstergelere ilişkin ağırlık değerlerini toplamı 1 olacak şekilde belirleyelim. Eşit ağırlıklandırma yapsak 1/20 = 0.05 oluyor. Hepsine 0.05 atadım ve aralarındaki karşılaştırmaya göre birini artırıp diğerini azalttım.

myWeights <- data.frame(
  Indicator = names(endeks[,-1]),
  Weight = c(0.02,0.03,0.05,0.03,0.04,0.09,0.09,0.07,0.06,0.05,
             0.08,0.05,0.02,0.05,0.03,0.05,0.06,0.01,0.06,0.06)
)
Indicator Weight
konut_kalite 0.02
issizlik 0.03
saglik_hizmet 0.05
okul_oncesi 0.03
egitim_hizmet 0.04
pm10_istasyon 0.09
orman_alan 0.09
sokak_gurultu 0.07
temizlik_hizmet 0.06
cinayet_oran 0.05
gece_yalniz 0.08
asayis_hizmet 0.05
internet_abone 0.02
kanalizasyon_sebeke 0.05
havalimani_erisim 0.03
toplu_tasima_hizmet 0.05
sinema_tiyatro 0.06
avm_alani 0.01
sosyal_hayat 0.06
mutluluk 0.06

Şimdi her bir ağırlığı o göstergeye ait sütunda yer alan değerler ile çarpacağız. Böylece Ağırlıklı Normalleştirilmiş Karar Matrisi oluşacak.

for(col in 1:ncol(m2)){
  
  for(row in 1:nrow(m2)){
    
    m2[row,col] <- m2[row,col] * myWeights$Weight[col]
    
  }
  
}

Adım 4) En İyi ve En Kötü Alternatifin Belirlenmesi

Tüm iller arasından her bir göstergenin maksimum ve minimum değeri bulunur.

\(x_j^b = max_{i=1}^{M} x_{ij}\)

\(x_j^w = min_{i=1}^{M} x_{ij}\)

Ağırlıklı Normalleştirilmiş Karar Matrisi’nde her bir göstergenin ilgili sütunundan pozitif ideal çözüm için en büyük değer, negatif ideal çözüm için ise en küçük değer seçilmiştir. Dikkat etmemiz gereken nokta, pozitif ideal çözüm için eğer gösterge pozitif ise maksimum; negatif ise minimum değer; negatif ideal çözüm için eğer gösterge pozitif ise minimum; negatif ise maksimum değer seçilir.

# pos: positive
# neg: negative

myDirections <- data.frame(
  Indicator = names(endeks[,-1]),
  Direction = c("neg","neg","pos","pos",
                "pos","neg","pos","neg",
                "pos","neg","pos","pos",
                "pos","pos","pos","pos",
                "pos","pos","pos","pos")
)
Indicator Direction
konut_kalite neg
issizlik neg
saglik_hizmet pos
okul_oncesi pos
egitim_hizmet pos
pm10_istasyon neg
orman_alan pos
sokak_gurultu neg
temizlik_hizmet pos
cinayet_oran neg
gece_yalniz pos
asayis_hizmet pos
internet_abone pos
kanalizasyon_sebeke pos
havalimani_erisim pos
toplu_tasima_hizmet pos
sinema_tiyatro pos
avm_alani pos
sosyal_hayat pos
mutluluk pos
pos_ideal <- numeric()
neg_ideal <- numeric()
criteria <- colnames(m2)

for(col in 1:ncol(m2)){
  
  # pozitif taraf için;
  
  p_name <- criteria[col]
  p_filter <- myDirections %>% 
    filter(Indicator == p_name) %>% 
    pull(Direction)
  
  p_ideal <- if_else(p_filter == "pos", max(m2[,col]), min(m2[,col]))
  pos_ideal <- c(pos_ideal,p_ideal)
  
  # negatif taraf için;
  
  n_name <- criteria[col]
  n_filter <- myDirections %>% 
    filter(Indicator == n_name) %>% 
    pull(Direction)
  
  n_ideal <- if_else(n_filter == "neg", max(m2[,col]), min(m2[,col]))
  neg_ideal <- c(neg_ideal,n_ideal)
  
}

pos_neg_ideal <- data.frame(
  "Indicator" = myDirections$Indicator,
  "PositiveIdeal" = pos_ideal,
  "NegativeIdeal" = neg_ideal
)
Indicator PositiveIdeal NegativeIdeal
konut_kalite 0.0009227 0.0043996
issizlik 0.0014571 0.0081181
saglik_hizmet 0.0063640 0.0038950
okul_oncesi 0.0049470 0.0021901
egitim_hizmet 0.0052983 0.0028718
pm10_istasyon 0.0030563 0.0191867
orman_alan 0.0192523 0.0000121
sokak_gurultu 0.0029607 0.0157113
temizlik_hizmet 0.0089772 0.0031494
cinayet_oran 0.0008939 0.0138624
gece_yalniz 0.0113660 0.0058765
asayis_hizmet 0.0062340 0.0038695
internet_abone 0.0041353 0.0005065
kanalizasyon_sebeke 0.0073085 0.0022736
havalimani_erisim 0.0193698 0.0000000
toplu_tasima_hizmet 0.0073563 0.0021898
sinema_tiyatro 0.0173789 0.0000338
avm_alani 0.0032476 0.0000000
sosyal_hayat 0.0097283 0.0025860
mutluluk 0.0084035 0.0045426

Adım 5) Öklid Uzaklığın Hesaplanması

Hedef alternatif ile en iyi ve en kötü alternatif arasındaki Öklid uzaklığı hesaplanır.

\(d_i^b = \sqrt{\sum_{j=1}^{N}(x_{ij}-x_j^b)^2}\)

\(d_i^w = \sqrt{\sum_{j=1}^{N}(x_{ij}-x_j^w)^2}\)

b_euclidean <- m2
w_euclidean <- m2

for(row in 1:nrow(m2)){
  
  for(col in 1:ncol(m2)){
    
    b_euclidean[row, col] <- (b_euclidean[row, col] - pos_neg_ideal$PositiveIdeal[col]) ** 2
    w_euclidean[row, col] <- (w_euclidean[row, col] - pos_neg_ideal$NegativeIdeal[col]) ** 2
    
  }
  
}

b_euclidean <- sqrt(rowSums(b_euclidean))
w_euclidean <- sqrt(rowSums(w_euclidean))

df_euclidean <- data.frame(
  prov_num = seq(1,length(il),1),
  b_euclidean = b_euclidean,
  w_euclidean = w_euclidean
)
prov_num b_euclidean w_euclidean
1 0.0201152 0.0259480
2 0.0322445 0.0180609
3 0.0303864 0.0221779
4 0.0345631 0.0185534
5 0.0271004 0.0257582
6 0.0254241 0.0239853
7 0.0217484 0.0258145
8 0.0251323 0.0285319
9 0.0257707 0.0221523
10 0.0247963 0.0254779

Adım 6) TOPSIS Skorunun Elde Edilmesi

Her alternatif için en kötü alternatife olan benzerliğinin hesaplandığı adımdır. Burada, TOPSIS skoru elde edilir.

\(s_i = \frac{d_i^w}{d_i^w + d_i^b}\)

topsis_score <- df_euclidean %>% 
  mutate(
    score = w_euclidean / (w_euclidean + b_euclidean),
    province = il
  ) %>% 
  arrange(desc(score)) %>% 
  mutate(rank = seq(1,nrow(.),1))
prov_num b_euclidean w_euclidean score province rank
34 0.0182616 0.0338457 0.6495390 İstanbul 1
77 0.0181110 0.0305289 0.6276518 Yalova 2
61 0.0194185 0.0269682 0.5813780 Trabzon 3
1 0.0201152 0.0259480 0.5633130 Adana 4
78 0.0234771 0.0301615 0.5623088 Karabük 5
35 0.0204943 0.0258802 0.5580705 İzmir 6
17 0.0225074 0.0270572 0.5458984 Çanakkale 7
7 0.0217484 0.0258145 0.5427442 Antalya 8
37 0.0254867 0.0293201 0.5349719 Kastamonu 9
8 0.0251323 0.0285319 0.5316751 Artvin 10

Adım 7) TOPSIS Skorunun Büyükten Küçüğe Doğru Sıralanması

Aşağıda ilk 10 il gösterilmiştir.

topsis_score_desc <- topsis_score %>% 
  select(province,score,rank)
province score rank
İstanbul 0.6495390 1
Yalova 0.6276518 2
Trabzon 0.5813780 3
Adana 0.5633130 4
Karabük 0.5623088 5
İzmir 0.5580705 6
Çanakkale 0.5458984 7
Antalya 0.5427442 8
Kastamonu 0.5349719 9
Artvin 0.5316751 10

Birinci sırada yaşadığım il olan İstanbul çıktı. TÜİK’in endeksinde birinci olan Isparta ise bu veri setine ve ağırlıklandırmalarıma göre yaşayacağım iller arasında 16. olmuştur.

Son olarak, topsis paketi ile aşağıdaki gibi çok kısa bir süre içerisinde sonuçlar elde edilebilir.

library(topsis)

m <- as.matrix(endeks[,-1]) # matris
w <- myWeights$Weight # ağırlıklar
i <- myDirections %>% 
  mutate(Direction = ifelse(Direction == "neg", "-", "+")) %>% 
  pull(Direction) # yönler

df <- topsis(m,w,i) %>% 
  mutate(province = il) %>% 
  arrange(desc(score))
ggplot(df %>% arrange(desc(score)) %>% slice(1:10),
       aes(x = reorder(province,score), y = score, fill = score)) +
  geom_col() +
  coord_flip() +
  theme_minimal() +
  theme(axis.title = element_blank(),
        legend.title = element_blank()) +
  scale_fill_gradient(low = "orange", high = "blue")

Yararlandığım Kaynaklar:

What is TOPSIS?