ggplot2
Kullanarak R’da Türkiye Şehir Haritası Çizdirmek
Herkese merhabalar!
Bundan yaklaşık iki sene önce R’da maps
ve 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.
Daha sonra verimizi readRDS
fonksiyonu ile okutuyoruz.
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.
İş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.
## # 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.
GID_0
: Ülke Kimlik NumarasıGID_1
: Şehirlerin kimlik numaraları, bu numaraları plaka kodları ile karıştırmayın.GID_2
: İlçelerin kimlik numaraları
Aynı şekilde,
NAME_0
: Ülke ismiNAME_1
: Şehir isimleriNAME_2
: İlçe İsimleri
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.
## Regions defined for each Polygons
## 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.
## # 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.
## [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"
## [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
## [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.
## # 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.
## # 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.
## 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.
##
## 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
##
## 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.
## 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.
## # 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! :)
## 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 ozancan@metu.edu.tr adresine gönderebilirsiniz.