Herkese merhabalar!

Bundan yaklaşık iki sene önce R’da mapsve ggplot2 paketleri kullanılarak Türkiye siyasi haritasının çizimini anlatmıştım. Konu ile ilgili tutoriala buradan ulaşabilirsiniz.

Şimdi ise işi biraz daha detaylandırıyoruz, bu sefer sadece ggplot2 paketi kullanarak bir şehrin ve ilçelerinin haritasını çizdirip, belirli bir değişkenin büyüklüğüne göre renklendireceğiz.

Kullanacağımız spatial datayı GADM’dan indiriyoruz.

İlk olarak Türkiye’yi seçip, dosya formatı olarak da R (SpatialPolygonsDataFrame) (yani .rds) ’i seçiyoruz.

Not: Buradan indireceğiniz veriyi ticari amaçla kullanamazsınız.

Ardından ekranınıza her bir R dosyasının yanında yazan level 0, level 1 ve level 2 seçeneklerini göreceksiniz. Bunlardan level 0, il ve ilçelerin olmadığı sadece Türkiye ülke sınırlarının yer aldığı dosyadır.Öte yandan level 1 il sınırlarının dahil olduğu, level 2 ise ilçe sınırlarının da dahil olduğu dosyadır. Bu örnekte il ve ilçe sınırlarıyla ilgilendiğimiz için biz level 2 i indiriyoruz.

İlk önce ggplot2 paketine ek veri düzenlenmesi ve okumasında kullanacağımız tidyverse ve sp paketlerini de yüklüyoruz.

library(tidyverse)
library(sp) # Konumsal (Spatial) veri için
library(ggplot2)

Daha sonra verimizi readRDS fonksiyonu ile okutuyoruz.

tr1<- readRDS("ililce.rds") #reading a spatial data
plot(tr1)

Verinizi okuttuktan sonra plot komutu ile kolayca görselleştirebilirsiniz, ancak başlıkta da belirtildiği gibi biz bu görselleştirmeyi ggplot2 kütüphanesinin komutlarını kullanarak yapacağız.

Bu tutorial’da Ankara ilini çizdireceğiz. Okuttuğumuz veri setinde il isimleri NAME_1 başlığı altında depolanmaktadır. tidyverse paketi altındaki subset komutunu kullanarak bu değişkenden Ankara’yı seçeceğiz.

ankara=tr1%>%subset(NAME_1=="Ankara")
plot(ankara)

İşte Ankara’nın ilçelere göre haritası, ama işimiz burada bitmiyor. Bu haritayı ilçelerin büyüklüğüne göre renklendireceğiz ve başlık vs gibi detaylar ekleyeceğiz.

Önce datanın içeriğini göstermek istiyorum.

ankara@data %>% as_tibble() %>% head(10) 
## # A tibble: 10 x 13
##    GID_0 NAME_0 GID_1 NAME_1 NL_NAME_1 GID_2 NAME_2 VARNAME_2 NL_NAME_2 TYPE_2
##    <chr> <chr>  <chr> <chr>  <chr>     <chr> <chr>  <chr>     <chr>     <chr> 
##  1 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Akyurt <NA>      <NA>      Distr~
##  2 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Altın~ <NA>      <NA>      Distr~
##  3 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Ayaş   <NA>      <NA>      Distr~
##  4 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Bala   <NA>      <NA>      Distr~
##  5 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Beypa~ <NA>      <NA>      Distr~
##  6 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Çamlı~ <NA>      <NA>      Distr~
##  7 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Çanka~ <NA>      <NA>      Distr~
##  8 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Çubuk  <NA>      <NA>      Distr~
##  9 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Elmad~ <NA>      <NA>      Distr~
## 10 TUR   Turkey TUR.~ Ankara <NA>      TUR.~ Etime~ <NA>      <NA>      Distr~
## # ... with 3 more variables: ENGTYPE_2 <chr>, CC_2 <chr>, HASC_2 <chr>

Datayı tibble dosyası haline getirdik, böylece ilerleyen aşamalarda tidyverse içerisinde yer alan tidyr kütüphanesindeki left_join komutunun kullanımını kolaylaştırdık. Ardından head komutu ile datanın ilk 10 satırına göz attık.

Aynı şekilde,

Elimizdeki tibble/spatial datayı data.frame objesi haline getirmeliyiz, bunun içinde ggplot2 paketi altındaki fortify fonksiyonu yardımıyla s3 objemizi df yapacağız.

ankdata<-fortify(ankara)
## Regions defined for each Polygons
head(ankdata)
##       long      lat order  hole piece     id    group
## 1 33.28255 40.00562     1 FALSE     1 117455 117455.1
## 2 33.20898 40.00539     2 FALSE     1 117455 117455.1
## 3 33.19685 40.00478     3 FALSE     1 117455 117455.1
## 4 33.18901 40.00371     4 FALSE     1 117455 117455.1
## 5 33.18213 40.00188     5 FALSE     1 117455 117455.1
## 6 33.16760 39.99602     6 FALSE     1 117455 117455.1

Şimdi ise TÜİK’ten elde ettiğim Ankara ilçeleri nüfus verisini okutuyorum. Elimdeki veri .xlsx objesi olduğu için readxl komutu yardımıyla bu datayı okutuyorum.

library(readxl)
nufus<-read_excel("ankaranufus.xlsx")
head(nufus)
## # A tibble: 6 x 2
##   İlce       Nufus
##   <chr>      <dbl>
## 1 Akyurt     36123
## 2 Altındağ  389510
## 3 Ayaş       13900
## 4 Bala       30280
## 5 Beypazarı  48371
## 6 Çamlıdere   9825

Bu noktada karşımıza ufak bir problem çıkıyor.

(ankara@data$NAME_2)
##  [1] "Akyurt"          "Altındağ"        "Ayaş"            "Bala"           
##  [5] "Beypazarı"       "Çamlıdere"       "Çankaya"         "Çubuk"          
##  [9] "Elmadağ"         "Etimesgut"       "Evren"           "Gölbaşı"        
## [13] "Güdül"           "Haymana"         "Kalecik"         "Kazan"          
## [17] "Keçiören"        "Kızılcahamam"    "Mamak"           "Nallıhan"       
## [21] "Polatlı"         "Sincan"          "Şultan Koçhisar" "Yenimahalle"
nufus$İlce
##  [1] "Akyurt"          "Altındağ"        "Ayaş"            "Bala"           
##  [5] "Beypazarı"       "Çamlıdere"       "Çankaya"         "Çubuk"          
##  [9] "Elmadağ"         "Etimesgut"       "Evren"           "Gölbaşı"        
## [13] "Güdül"           "Haymana"         "Kahramankazan"   "Kalecik"        
## [17] "Keçiören"        "Kızılcahamam"    "Mamak"           "Nallıhan"       
## [21] "Polatlı"         "Pursaklar"       "Sincan"          "Şereflikoçhisar"
## [25] "Yenimahalle"

Görüldüğü üzere spatial data ve okuttuğumuz datada isimleri içinde farklılıklar var. Örn: Şultan Koçhisar ve Şereflikoçhisar. Bu sorunun çözümü için ise gsub fonksiyonunu kullanacağız. Bu fonksiyon karakter yapısındaki bir değişkenin içerisinde yer alan bir ya da birden fazla harfin değiştirilmesinde kullanılan bir fonksiyon.

Örnek

x <- "Ozancan"
gsub("an","on",x)
## [1] "Ozoncon"
ankara@data$NAME_2<-gsub("Şultan Koçhisar" ,"Şereflikoçhisar",ankara@data$NAME_2)
(ankara@data$NAME_2)
##  [1] "Akyurt"          "Altındağ"        "Ayaş"            "Bala"           
##  [5] "Beypazarı"       "Çamlıdere"       "Çankaya"         "Çubuk"          
##  [9] "Elmadağ"         "Etimesgut"       "Evren"           "Gölbaşı"        
## [13] "Güdül"           "Haymana"         "Kalecik"         "Kazan"          
## [17] "Keçiören"        "Kızılcahamam"    "Mamak"           "Nallıhan"       
## [21] "Polatlı"         "Sincan"          "Şereflikoçhisar" "Yenimahalle"

Gördüğünüz gibi sorun çözüldü. :)

Şimdi bu iki datayı birbiriyle birleştireceğiz, ancak bunun için önce nüfus datasını da tibble objesi haline getirmeliyiz.

nufus%>%as_tibble
## # A tibble: 25 x 2
##    İlce       Nufus
##    <chr>      <dbl>
##  1 Akyurt     36123
##  2 Altındağ  389510
##  3 Ayaş       13900
##  4 Bala       30280
##  5 Beypazarı  48371
##  6 Çamlıdere   9825
##  7 Çankaya   944609
##  8 Çubuk      90764
##  9 Elmadağ    45557
## 10 Etimesgut 587052
## # ... with 15 more rows

Artık left_join kullanarak iki datayı da birleştirebiliriz.

ilcenufus<- data_frame(id = rownames(ankara@data), İlce = ankara@data$NAME_2) %>% left_join(nufus, by = "İlce")
## Warning: `data_frame()` is deprecated as of tibble 1.1.0.
## Please use `tibble()` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_warnings()` to see where this warning was generated.
ilcenufus
## # A tibble: 24 x 3
##    id     İlce       Nufus
##    <chr>  <chr>      <dbl>
##  1 117454 Akyurt     36123
##  2 117763 Altındağ  389510
##  3 117152 Ayaş       13900
##  4 118254 Bala       30280
##  5 116485 Beypazarı  48371
##  6 115580 Çamlıdere   9825
##  7 117911 Çankaya   944609
##  8 115990 Çubuk      90764
##  9 117819 Elmadağ    45557
## 10 117922 Etimesgut 587052
## # ... with 14 more rows

Şimdi her ilçenin ID’sine karşılık gelecek şekilde nüfusularını da ekledik.

Artık son aşama. ggplot2 kullanarak haritalama işlemi yapmak istiyorsanız elinizdeki datada mutlaka lattitude ve longitude değerleri olmak zorunda. Bu yüzden birkez daha left_join kullanarak bir önceki stepte oluşturduğumuz dataya ilçelerim lattitude ve longitude değerlerini ekliyoruz.

final_map <- left_join(ankdata, ilcenufus, by = "id")
head(final_map)
##       long      lat order  hole piece     id    group İlce Nufus
## 1 33.28255 40.00562     1 FALSE     1 117455 117455.1 <NA>    NA
## 2 33.20898 40.00539     2 FALSE     1 117455 117455.1 <NA>    NA
## 3 33.19685 40.00478     3 FALSE     1 117455 117455.1 <NA>    NA
## 4 33.18901 40.00371     4 FALSE     1 117455 117455.1 <NA>    NA
## 5 33.18213 40.00188     5 FALSE     1 117455 117455.1 <NA>    NA
## 6 33.16760 39.99602     6 FALSE     1 117455 117455.1 <NA>    NA

Ops! Bir hatayla karşılaştık. İlçe ve nüfus değişkenleri datamıza eklenmemiş.Bunun sebebi muhtemelen ortak değişkenimiz olan ID elbette.

Eğer üst dataki ID ile final_map’teki ID değerlerine bakarsak, ufak bir sorun olduğunu göreceğiz.

table(ilcenufus$id)
## 
## 115354 115580 115990 116485 116521 116624 116790 117048 117152 117326 117454 
##      1      1      1      1      1      1      1      1      1      1      1 
## 117548 117641 117763 117819 117911 117913 117922 118078 118225 118254 118515 
##      1      1      1      1      1      1      1      1      1      1      1 
## 119265 119645 
##      1      1
table(final_map$id)
## 
## 115355 115581 115991 116486 116522 116625 116791 117049 117153 117327 117455 
##    207    105    178    183    173    156     80     85    165     66     64 
## 117549 117642 117764 117820 117912 117914 117923 118079 118226 118255 118516 
##     95    142     65     90     60     88     39    267    119    169    231 
## 119266 119646 
##    218     85

İki çıktıdan anlaşıldığı üzere ankdata objesindeki id değerleri ilcenufus id değerlerinden bir fazla. O halde ilcenufus datasının id değerlerine 1 eklersek bu sorunu çözebiliriz.

str(ilcenufus)
## tibble [24 x 3] (S3: tbl_df/tbl/data.frame)
##  $ id   : chr [1:24] "117454" "117763" "117152" "118254" ...
##  $ İlce : chr [1:24] "Akyurt" "Altındağ" "Ayaş" "Bala" ...
##  $ Nufus: num [1:24] 36123 389510 13900 30280 48371 ...

ilcenufus datasında id karakter objesi olarak duruyor, onu numeric’e çevirip 1 ekleyip daha sonra karater yapmalıyız.

ilcenufus$id=as.character(as.numeric(ilcenufus$id)+1)
head(ilcenufus)
## # A tibble: 6 x 3
##   id     İlce       Nufus
##   <chr>  <chr>      <dbl>
## 1 117455 Akyurt     36123
## 2 117764 Altındağ  389510
## 3 117153 Ayaş       13900
## 4 118255 Bala       30280
## 5 116486 Beypazarı  48371
## 6 115581 Çamlıdere   9825

Sorun halloldu! :)

final_map1 <- left_join(ankdata, ilcenufus, by = "id")
head(final_map1)
##       long      lat order  hole piece     id    group   İlce Nufus
## 1 33.28255 40.00562     1 FALSE     1 117455 117455.1 Akyurt 36123
## 2 33.20898 40.00539     2 FALSE     1 117455 117455.1 Akyurt 36123
## 3 33.19685 40.00478     3 FALSE     1 117455 117455.1 Akyurt 36123
## 4 33.18901 40.00371     4 FALSE     1 117455 117455.1 Akyurt 36123
## 5 33.18213 40.00188     5 FALSE     1 117455 117455.1 Akyurt 36123
## 6 33.16760 39.99602     6 FALSE     1 117455 117455.1 Akyurt 36123
ggplot(final_map1) +geom_polygon( aes(x = long, y = lat, group = group, fill = Nufus), color = "grey") +
coord_map() +theme_void() + labs(title = "Ankara'nın İlçelere Göre Nüfus Dağılımı",subtitle = "Kaynak: Türkiye Istatistik Kurumu",caption="Twitter/@OzancanOzdemir") +
scale_fill_gradient(low = "pink", high = "red",na.value = "white") +
theme(plot.title = element_text(hjust = 0.5),plot.subtitle = element_text(hjust = 0.5))

Soru ve görüşlerinizi adresine gönderebilirsiniz.