Paket | Açıklama |
---|---|
tidyverse | Çoğunlukla veri manipülasyonu ve görselleştirme üzerine paketler içeren bir paket koleksiyonu |
sf | Simple Features: Mekânsal vektör verileri işlemek için |
terra | Raster verileri işlemek için |
tidyterra | terra paketi için tidyverse metotları sağlayan bir paket |
mapview | İnteraktif haritalar için |
rgeoboundaries | Mülki idare sınırlarını indirmek için |
R ve Kuşlar - eBird Verilerinin R ile Analizi II
Merhabalar, blogun ikinci yazısına hoş geldiniz. Takıldığınız ve anlamadığınız yerler olursa lütfen yorum yapmaya çekinmeyiniz. Ayrıca katkılarınızı ve eleştirilerinizi de bekliyorum. Keyifli okumalar.
Blogun ilk yazısını yazarken, ikincisi de birkaç haftaya çıkar, nasıl olsa kodlar hazır diye düşünüyordum ancak tezdir, iştir derken uzadı. Yoğunluk yetmiyormuş gibi bilgisayarın format ihtiyacı ve NTFS dosya sistemine sahip harici diskin linux ile uyumsuzluğu da eklenince yazının taslağı ve kodlarını kaybettim. Sonuç olarak -birbirinden güzel bahanelerimi özetleyecek olursam- gecikmiş, kaybedilmiş ve sıfırdan yazılmış bir yazıyla karşınızdayım.
Bu blog yazısı, bir öncekinin devamı niteliğinde sayılabilir. R ile eBird verilerini işlemeye devam edeceğiz. İlk yazıda birinci soru üzerine odaklanmıştık, bunda ise ikinci soruya odaklanacağız:
- Bilindiği gibi Kızılcahamam, Türkiye’deki en önemli kara akbaba - Aegypius monachus popülasyonlarından birisini barındırıyor. Bu türün, Kızılcahamam ilçe sınırları içerisinde nasıl bir dağılımı vardır? Türün dağılımıyla çevresel faktörler arasındaki ilişki kabaca nasıldır?
Temel R ve GIS bilgisine sahip olmanız yazıdaki birçok yeri anlamanız için yeterli olacaktır. Ancak bu alanlarda yeniyseniz de endişelenmeyin. Anlamadığınız her şeyi yorum olarak sorabilirsiniz. Blogun da ana amaçlarından birisi bu zaten. Ayrıca kuşlara ilginiz olmasa bile, bu yazının bazı temel mekânsal analizleri öğrenmek için faydalı olacağını düşünüyorum.
Yazınının Akışı
Yazının genel akışı aşağıdaki gibidir:
- Paketlerin yüklenmesi
- İlçe verisinin işleri
- Kuş verisinin işleri
- DEM verisinin işleri
- Topografik hesaplamalar
- Verinin görselleştirilmesi
1. Paketlerin yüklenmesi
Bu paketler kurulu değilse aşağıdaki kod bloğu ile kurabilirsiniz. Bu kod bloğu, paketi R’a yüklemeye çalışacak, eğer yükleyemezse kuracaktır. Paketler kuruluysa, library() fonksiyonu ile yükleyebiliriz.
# eger paketler yuklu degilse onlari kur
if (!require("tidyverse")) install.packages("tidyverse")
if (!require("sf")) install.packages("sf")
if (!require("terra")) install.packages("terra")
if (!require("tidyterra")) install.packages("tidyterra")
if (!require("mapview")) install.packages("mapview")
if (!require("rgeoboundaries")) remotes::install_github("wmgeolab/rgeoboundaries")
# paketleri R'a yukle
library(tidyverse) # bircok veri isini kolaylastirmak için
library(sf) # r'da mekansal vektor verileri islemek icin
library(terra) # r'da mekansal raster verileri islemek icin
library(tidyterra) # terra ile tidyverse metotlari kullanmak icin
library(mapview) # interaktif haritalar cizmek icin
library(rgeoboundaries) # tr ilce sinirlarina erismek icin
2. İlçe verisinin işleri
İkinci soruya cevap verebilmek için kuş, ilçe sınırları ve dijital yükseklik modeline (DEM) ihtiyacımız var. İlk ilçeden başlayalım. Kuş ve DEM verisini işlemek için ilçeye ihtiyaç duyacağız ne de olsa.
İlk yazıda olduğu gibi bu sefer de geoBoundaries verisini kullanacağız. Şimdi ilçe verilerini indirip, içinden Kızılcahamam’ı çıkartalım.
<- gb_adm2(country = "Turkey", type = "SSCGS") # type = "SSCGS" argumaniyla basitlestirilmiş versiyonunu indiriyoruz
tr_ilce <- tr_ilce[tr_ilce$shapeName == "Kızılcahamam", ]
khamam khamam
Simple feature collection with 1 feature and 6 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 32.27539 ymin: 40.21093 xmax: 32.91882 ymax: 40.75389
Geodetic CRS: WGS 84
shapeGroup shapeType shapeName shapeISO shapeID
388 TUR ADM2 Kızılcahamam <NA> 54988432B2925959455693
shapeCanonical geometry
388 Districts MULTIPOLYGON (((32.51627 40...
Kızılcahamam’ı doğru bir şekilde aldık gibi görünüyor. Verimizi {mapview} paketini kullanarak görselleştirelim, bir kontrol edelim. Bu paket, interaktif haritalar yapmak için oldukça işlevsel.
mapview(khamam)
Gördüğünüz gibi her şey yolunda. :)
3. Kuş verisinin işleri
Kara akbaba - Aegypius monachus, Avrasya’da geniş dağılıma sahip bir yırtıcı türü. 3 metreye varan kanat açıklığıyla en büyük kuşlardan birisi ve azalan bir popülasyona sahip. Türkiye, türün en önemli yaşam alanlarından birisi. Tür, özellikle Kuzey Anadolu’da, orman - bozkır geçişindeki yaşlı ormanları tercih ediyor. Bu alanlardan birisi de bu yazıda incelediğimiz yer olan Kızılcahamam. Kızılcahamam’ın yaşlı karaçam - Pinus nigra ormanları, türün üremesi için oldukça elverişli.
Türle alakalı kısa bir bilgi verdikten sonra verilere tekrardan dönebiliriz. Kuş verisini nasıl elde ettiğimize ilk yazıda değinmiştik. Tekrardan uzun uzun anlatmaya gerek yok.
Öncelikle kuş verimizi R’a yükleyelim:
<- read_delim("./ebird/ebd_TR_relApr-2023.txt") ebird
print(ebird)
# A tibble: 2,403,720 × 50
`GLOBAL UNIQUE IDENTIFIER` `LAST EDITED DATE` `TAXONOMIC ORDER` CATEGORY
<chr> <dttm> <dbl> <chr>
1 URN:CornellLabOfOrnithology:E… 2021-04-15 12:59:44 10043 species
2 URN:CornellLabOfOrnithology:E… 2021-04-15 12:58:56 5625 species
3 URN:CornellLabOfOrnithology:E… 2021-04-15 13:04:32 1361 species
4 URN:CornellLabOfOrnithology:E… 2021-04-14 00:03:13 22215 species
5 URN:CornellLabOfOrnithology:E… 2021-04-05 11:01:32 5787 species
6 URN:CornellLabOfOrnithology:E… 2021-04-21 02:26:13 29239 species
7 URN:CornellLabOfOrnithology:E… 2021-04-14 00:03:35 22156 species
8 URN:CornellLabOfOrnithology:E… 2021-04-05 11:01:32 291 species
9 URN:CornellLabOfOrnithology:E… 2018-09-20 02:46:53 5945 species
10 URN:CornellLabOfOrnithology:E… 2018-09-20 02:46:53 5945 species
# ℹ 2,403,710 more rows
# ℹ 46 more variables: `TAXON CONCEPT ID` <chr>, `COMMON NAME` <chr>,
# `SCIENTIFIC NAME` <chr>, `SUBSPECIES COMMON NAME` <chr>,
# `SUBSPECIES SCIENTIFIC NAME` <chr>, `EXOTIC CODE` <chr>,
# `OBSERVATION COUNT` <chr>, `BREEDING CODE` <chr>,
# `BREEDING CATEGORY` <chr>, `BEHAVIOR CODE` <chr>, `AGE/SEX` <chr>,
# COUNTRY <chr>, `COUNTRY CODE` <chr>, STATE <chr>, `STATE CODE` <chr>, …
Gördüğünüz gibi 2,403,720 gözlem (satır) ve 50 değişkene (sütun) sahip bir veri tablomuz var. Bu verilerin çoğuna ihtiyaç duymuyoruz. Dolayısıyla işimize yaramayanlardan kurtulmamız işimizi çokça kolaylaştıracaktır. Sadece işimize yarayan sütunları seçip, kara akbaba türüne ait gözlemleri içerecek şekilde filtreleyelim.
<- ebird |>
karaakbaba select(6, 7, 11, 12, 29, 30) |> # burada indeks kullanarak sectik, sutun isimleriyle de secebiliriz
filter(`SCIENTIFIC NAME` == "Aegypius monachus")
karaakbaba
# A tibble: 1,910 × 6
`COMMON NAME` `SCIENTIFIC NAME` `OBSERVATION COUNT` `BREEDING CODE` LATITUDE
<chr> <chr> <chr> <chr> <dbl>
1 Cinereous Vul… Aegypius monachus 1 <NA> 40.5
2 Cinereous Vul… Aegypius monachus 5 <NA> 40.5
3 Cinereous Vul… Aegypius monachus 1 <NA> 40.0
4 Cinereous Vul… Aegypius monachus 3 <NA> 40.5
5 Cinereous Vul… Aegypius monachus 1 <NA> 40.5
6 Cinereous Vul… Aegypius monachus 1 <NA> 40.5
7 Cinereous Vul… Aegypius monachus 2 <NA> 40.5
8 Cinereous Vul… Aegypius monachus 2 <NA> 40.5
9 Cinereous Vul… Aegypius monachus 1 <NA> 40.5
10 Cinereous Vul… Aegypius monachus 2 <NA> 40.5
# ℹ 1,900 more rows
# ℹ 1 more variable: LONGITUDE <dbl>
Şimdi değişken sayımız 6’ya, gözlem sayımız ise 1910’a düştü. Veri, çok daha yönetilebilir bir hâlde. Bu etkiyi, değişken isimlerini değiştirerek daha da artırabiliriz. Daha kısa, tamamı küçük harflerden oluşan, latinize ve boşluklar yerine alt çizgi kullandığımız isimler daha kullanışlı olacaktır. Herhangi bir hatayla karşılaşma riskimiz düşecektir. Bunun için ilk olarak karaakbaba data frame’inin değişken (sütun) isimlerine bakalım. names() ya da colnames() fonksiyonunu kullanabiliriz.
names(karaakbaba)
[1] "COMMON NAME" "SCIENTIFIC NAME" "OBSERVATION COUNT"
[4] "BREEDING CODE" "LATITUDE" "LONGITUDE"
Şimdi de yeni isimlerden oluşan bir karakter vektörü oluşturalım ve bunu karaakbaba data frame’inin değişken isimlerine atayalım.
names(karaakbaba) <- c(
"eng_name", "sci_name", "obs_count", "breeding_code", "y", "x"
)names(karaakbaba)
[1] "eng_name" "sci_name" "obs_count" "breeding_code"
[5] "y" "x"
Gördüğünüz gibi değişken isimlerini istediğimiz gibi değiştirdik.
Artık ilk yüklediğimiz eBird verisini R’dan silebiliriz. Bu veri, 2 milyondan fazla gözlemden oluştuğu için RAM’in şişmesine ve R’ın çökmesine yol açabilir. Ardından da çöp toplayıcıyı (garbage collector) çalıştırmak faydalı olacaktır. R, bu işi genelde otomatik yapıyor ancak büyük veriler silindiği zaman gc()’nin çalıştırılması öneriliyor.
rm(ebird)
gc()
used (Mb) gc trigger (Mb) max used (Mb)
Ncells 5214804 278.6 12641914 675.2 9219575 492.4
Vcells 10616247 81.0 127597023 973.5 148118395 1130.1
Şimdi de mekânsallaştırmaya geçebiliriz. Verimiz şu anda bir data frame. Dolayısıyla onunla mekânsal işler yapmak için verimizi mekânsallaştırmamız gerekiyor. Bunun için {sf} paketini kullanacağız. Bu paket, mekânsal vektör veriler işlemek için geliştirmiş, OGC (Open Geospatial Consortium) standardı bir paket. Ben de işlerimin büyük bir kısmında onu tercih ediyorum.
Koordinatların olduğu sütunları ve koordinat sistemini tanımlayarak verimizi sf objesine dönüştürelim.
<- st_as_sf(
karaakbaba_sf coords = c("x", "y"), crs = "EPSG:4326"
karaakbaba,
) karaakbaba_sf
Simple feature collection with 1910 features and 4 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: 26.50652 ymin: 36.02635 xmax: 44.5648 ymax: 42.0362
Geodetic CRS: WGS 84
# A tibble: 1,910 × 5
eng_name sci_name obs_count breeding_code geometry
* <chr> <chr> <chr> <chr> <POINT [°]>
1 Cinereous Vulture Aegypius… 1 <NA> (32.62995 40.46758)
2 Cinereous Vulture Aegypius… 5 <NA> (32.62995 40.46758)
3 Cinereous Vulture Aegypius… 1 <NA> (34.61423 40.01914)
4 Cinereous Vulture Aegypius… 3 <NA> (32.62995 40.46758)
5 Cinereous Vulture Aegypius… 1 <NA> (32.6622 40.48013)
6 Cinereous Vulture Aegypius… 1 <NA> (32.62403 40.4557)
7 Cinereous Vulture Aegypius… 2 <NA> (32.62403 40.4557)
8 Cinereous Vulture Aegypius… 2 <NA> (32.62403 40.4557)
9 Cinereous Vulture Aegypius… 1 <NA> (32.62403 40.4557)
10 Cinereous Vulture Aegypius… 2 <NA> (32.62403 40.4557)
# ℹ 1,900 more rows
Kara akbaba verisi artık mekânsal bir formatta. Geometri tipi, koordinat sistemi gibi öznitelikler barındırıyor.
Veriyi daha iyi tanımak için ilk görselleştirmeleri yapalım. Acaba kara akbabalar Türkiye’de nasıl dağılıyor? Bunun için tekrardan mapview() fonksiyonunu kullanıyoruz.
mapview(karaakbaba_sf)
Bu işlem de tamam. Gördüğünüz gibi ülkemizin kuzeyinde yoğunlaşan bir popülasyon mevcut.
Sıra geldi kuş verimizin Kızılcahamam’a göre alt kümesini almaya.
<- karaakbaba_sf[khamam, ]
karaakbaba_subset karaakbaba_subset
Simple feature collection with 139 features and 4 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: 32.29039 ymin: 40.24768 xmax: 32.8661 ymax: 40.64056
Geodetic CRS: WGS 84
# A tibble: 139 × 5
eng_name sci_name obs_count breeding_code geometry
<chr> <chr> <chr> <chr> <POINT [°]>
1 Cinereous Vulture Aegypius… 1 <NA> (32.62995 40.46758)
2 Cinereous Vulture Aegypius… 5 <NA> (32.62995 40.46758)
3 Cinereous Vulture Aegypius… 3 <NA> (32.62995 40.46758)
4 Cinereous Vulture Aegypius… 1 <NA> (32.6622 40.48013)
5 Cinereous Vulture Aegypius… 1 <NA> (32.62403 40.4557)
6 Cinereous Vulture Aegypius… 2 <NA> (32.62403 40.4557)
7 Cinereous Vulture Aegypius… 2 <NA> (32.62403 40.4557)
8 Cinereous Vulture Aegypius… 1 <NA> (32.62403 40.4557)
9 Cinereous Vulture Aegypius… 2 <NA> (32.62403 40.4557)
10 Cinereous Vulture Aegypius… 2 <NA> (32.62403 40.4557)
# ℹ 129 more rows
Kızılcahamam’da, eBird veritabanında kayıtlı 139 tane kara akbaba kaydı varmış. Bunlara bir göz atıp DEM verisiyle ilgilenmeye başlayalım. Kara akbaba dağılımıyla alakalı asıl haritayı en son yapacağız.
plot(
st_geometry(khamam),
main = "Kızılcahamam'da Kara Akbaba Dağılımı",
lwd = 2,
border = "grey30",
axes = TRUE,
reset = FALSE
) plot(
st_geometry(karaakbaba_subset),
cex = 1,
pch = 3,
lwd = 1.5,
add = TRUE
)
Hemen hızlıca mapview ile de bakalım.
mapview(khamam, lwd = 3, alpha.regions = 0) + mapview(karaakbaba_subset)
4. DEM verisinin işleri
Kara akbabanın Kızılcahamam’daki dağılımını ortaya çıkarttık. Şimdi de bazı çevresel değişkenlerle ilişkisi nasılmış, -kabaca- ona bakalım. Ben, topografik değişkenlerle olan ilişkisini merak ettim ve bu sebeple DEM verisine bakacağız.
DEM (Digital Elevation Model), kısaca, yeryüzünün yükseklik bilgisini sayısal olarak temsil eden modele verilen isim. Her bir grid için, sahip olduğu yükseklik verisini barındırır. Topografik ve hidrolojik birçok analizde sıklıkla kullanılıyor. Rakımın biyolojik sistemlerdeki önemi nedeniyle, ekoloji ve biyocoğrafyada da yaygın bir kullanımı var.
Burada COP-DEM (Copernicus DEM) kullandım. Veriye şu bağlantıdan ulaşabilirsiniz. Belki daha sonra bu verinin nereden, nasıl indirilebileceğiyle alakalı bir başka yazı yazarım.
DEM verisi, raster formatında bir veri. Raster veriyi, bir tür resim ya da bir tür matris olarak düşünebilirsiniz. Bu veri, hücrelerden - gridlerden oluşur ve her bir grid için bir değer içerir. Genellikle, yükseklik, eğim, sıcaklık, yağış gibi sürekli veriler bu formattadır.
Biz bu veri için {terra} paketini kullanacağız. Oldukça hızlı ve işlevsel bir paket.
# dem verisini yukleyelim
<- rast("./dem_4326.tif")
dem dem
class : SpatRaster
dimensions : 7556, 22983, 1 (nrow, ncol, nlyr)
resolution : 0.0008333333, 0.0008333333 (x, y)
extent : 25.66542, 44.81792, 35.80792, 42.10458 (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (EPSG:4326)
source : dem_4326.tif
name : Copernicus_DSM_COG_30_N35_00_E025_00_DEM
min value : -86.01817
max value : 5107.41357
Veriyi yazdırdığımızda, çözünürlüğünden, dört köşesinin koordinatına ve koordinat sistemine kadar birçok detayı görebiliyoruz.
plot(dem)
Kolayca haritasını da çizebiliyoruz. Gördüğünüz gibi Türkiye topografik haritası.
Şimdi verimizi Kızılcahamam ilçe sınırlarına göre maskeleyelim. khamam, sf formatında olduğu için vect() ile {terra}’nın kendi vektör veri tipi olan SpatVector’e dönüştürüyoruz.
<- crop(dem, vect(khamam), mask = TRUE)
dem_subset dem_subset
class : SpatRaster
dimensions : 651, 772, 1 (nrow, ncol, nlyr)
resolution : 0.0008333333, 0.0008333333 (x, y)
extent : 32.27542, 32.91875, 40.21125, 40.75375 (xmin, xmax, ymin, ymax)
coord. ref. : lon/lat WGS 84 (EPSG:4326)
source(s) : memory
varname : dem_4326
name : Copernicus_DSM_COG_30_N35_00_E025_00_DEM
min value : 749.5305
max value : 2069.5696
plot(dem_subset)
5. Topografik hesaplamalar
terrain() ile eğim ve bakıyı hesaplayalım.
<- terrain(dem_subset, "slope")
slp <- terrain(dem_subset, "aspect") asp
par(mfrow = c(1, 2))
plot(slp, main = "Kızılcahamam Eğim Haritası")
plot(asp, main = "Kızılcahamam Bakı Haritası")
Şimdi de her bir kara akbaba gözlem noktasının sahip olduğu çevresel değişkenleri çıkartalım ve ardından karaakbaba verisiyle birleştirelim.
$ID <- 1:nrow(karaakbaba_subset)
karaakbaba_subset
<- extract(dem, vect(karaakbaba_subset))
ext_dem <- extract(slp, vect(karaakbaba_subset))
ext_slp <- extract(asp, vect(karaakbaba_subset))
ext_asp
<- left_join(karaakbaba_subset, ext_dem, by = "ID")
ext_dem <- left_join(ext_dem, ext_slp, by = "ID")
ext_slp <- left_join(ext_slp, ext_asp, by = "ID")
ext_asp
<- ext_asp
karaakbaba_ext names(karaakbaba_ext)[7] <- "altitude"
glimpse(karaakbaba_ext)
Rows: 139
Columns: 9
$ eng_name <chr> "Cinereous Vulture", "Cinereous Vulture", "Cinereous Vul…
$ sci_name <chr> "Aegypius monachus", "Aegypius monachus", "Aegypius mona…
$ obs_count <chr> "1", "5", "3", "1", "1", "2", "2", "1", "2", "2", "2", "…
$ breeding_code <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, NA, …
$ geometry <POINT [°]> POINT (32.62995 40.46758), POINT (32.62995 40.4675…
$ ID <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 1…
$ altitude <dbl> 1058.8070, 1058.8070, 1058.8070, 1045.1802, 1136.2458, 1…
$ slope <dbl> 11.188035, 11.188035, 11.188035, 22.408733, 11.157285, 1…
$ aspect <dbl> 309.599090, 309.599090, 309.599090, 242.915925, 7.856463…
Gördüğünüz gibi kara akbaba verimizin içinde artık her bir nokta için rakım, eğim ve bakı bilgisi mevcut. Bu aşamadan sonra modellerle çalışabiliriz ancak bu, bu yazının konusu değil. Ayrıca elimizdeki veri bunun için ne kadar yeterli, ayrı bir tartışma konusu. Şimdi çıkarttığımız topografik verilere bir göz atıp asıl haritamızı yapmaya geçebiliriz.
|>
karaakbaba_ext st_drop_geometry() |>
pivot_longer(cols = c("altitude", "slope", "aspect")) |>
ggplot(aes(x = value, fill = name, colour = "name")) +
geom_histogram(alpha = .6) +
scale_fill_viridis_d() +
scale_color_viridis_d() +
theme_minimal() +
theme(
legend.position="none",
+
) facet_wrap(~name, scales = "free_x")
6. Verinin görselleştirilmesi
Uzun bir yazı oldu yine ancak sonuna geldik. Şimdi Kızılcahamam’daki kara akbaba gözlemlerinin dağılımını, DEM ile birlikte görselleştirmeye çalışalım.
ggplot() + # grafigi baslatiyor
geom_spatraster( # dem verisini ekliyoruz
data = dem_subset,
na.rm = TRUE
+
) geom_sf( # kizilcahamam ilce sinirlarini ekliyoruz
data = khamam,
fill = NA
+
) geom_sf( # kara akbaba gozlem verisini ekliyoruz
data = karaakbaba_subset,
aes()
+
) scale_fill_wiki_c() + # dem verisi icin renk paleti ekliyoruz
labs( # etiketleri yaziyoruz
title = "Kara Akbaba Dağılım Haritası",
subtitle = "Kızılcahamam'daki kara akbaba gözlemlerinin dağılımı",
fill = "Yükseklik (m)",
caption = "Veri: eBird | COP-DEM"
+
) theme_minimal() + # tema seciyoruz
theme( # temanin ozelliklerini belirliyoruz
plot.background = element_rect("white", colour = "white"),
text = element_text(family = "ubuntu mono")
)
Güzel oldu sanki. :)
Bilimle ve huzurla kalınız.