我們需要使用一些 R 套件來處理和繪圖,像是 tidyverse(處理資料)和 ggplot2(繪圖)。也可能需要 lubridate 來處理時間資料。
# install.packages(c("tidyverse", "lubridate", "httr", "jsonlite"))
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.3 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(lubridate)
library(httr)
library(jsonlite)
##
## Attaching package: 'jsonlite'
##
## The following object is masked from 'package:purrr':
##
## flatten
我們可以使用 iNaturalist API 先查詢物種和地點的 ID。
查詢物種的 taxon_id 例如,查詢八哥屬和藍磯鶇的 taxon_id:
get_taxon_id <- function(species_name, rank) {
base_taxa_url <- paste0("https://api.inaturalist.org/v1/")
response <- RETRY(verb = "GET",
url = base_taxa_url,
path = "v1/taxa",
query = list(q = species_name,
rank = rank,
order = "desc")
)
data <- fromJSON(content(response, "text"), flatten = TRUE)
taxon_id <- data$results$id # 取得第一個匹配的taxon_id
return(taxon_id)
}
# 取得八哥屬和藍磯鶇的taxon_id
taxon_id_monticola <- get_taxon_id("Monticola solitarius", "species") # 13141
taxon_id_acridotheres <- get_taxon_id("Acridotheres", "genus") # 14868
透過 taxon_id 和 place_id 取得觀察資料:
# Define place IDs of interest
places_id <- c(7887, 6737) # Taiwan = 7887, Japan = 6737
place_id_taiwan <- places_id[1]
place_id_japan <- places_id[2]
# 取得藍磯鶇在台灣和日本的資料
## 藍磯鶇(研究等級)@台灣、日本
## https://www.inaturalist.org/observations?place_id=7887&quality_grade=research&subview=table&taxon_id=13141
## unzip("data/inat_monticola_20240922download/observations-479259.csv.zip", exdir = "data/inat_monticola_20240922download/")
data_monticola <- read_csv("data/inat_monticola_20240922download/observations-479259.csv")
## Rows: 2308 Columns: 39
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (23): observed_on_string, time_observed_at, time_zone, user_login, user...
## dbl (10): id, user_id, num_identification_agreements, num_identification_di...
## lgl (5): captive_cultivated, private_place_guess, private_latitude, privat...
## date (1): observed_on
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
## 八哥屬(研究等級)@台灣、日本
## quality_grade=research&identifications=any&place_id=7887,6737&taxon_id=13141&spam=false
## unzip("data/inat_acridotheres_20240922download/observations-479263.csv.zip", exdir = "data/inat_acridotheres_20240922download/")
data_acridotheres <- read_csv("data/inat_acridotheres_20240922download/observations-479263.csv")
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 6993 Columns: 39
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (23): observed_on_string, time_observed_at, time_zone, user_login, user...
## dbl (10): id, user_id, num_identification_agreements, num_identification_di...
## lgl (5): captive_cultivated, private_place_guess, private_latitude, privat...
## date (1): observed_on
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
利用 ggplot2 來繪製物種隨時間的分布圖。
library(rnaturalearth)
## Warning: package 'rnaturalearth' was built under R version 4.3.2
# extract eastern Asia region from world
world <- ne_countries(scale = "medium", continent = "asia")
# targetRegion2 <- world %>% filter(region_wb=="South Asia" | region_wb == "East Asia & Pacific" & subregion != "Australia and New Zealand")
targetRegion <- world %>% filter(admin %in% c("Japan", "Taiwan"))
# Summarize and prepare data for plotting
data_monticola_clean <- data_monticola %>%
drop_na(time_observed_at) %>%
mutate(year = year(time_observed_at)) %>%
mutate(birdTaxa = "藍磯鶇")
data_acridotheres_clean <- data_acridotheres %>%
drop_na(time_observed_at) %>%
mutate(year = year(time_observed_at)) %>%
mutate(birdTaxa = "八哥屬")
data_combine <- bind_rows(data_monticola_clean, data_acridotheres_clean) %>%
select(birdTaxa, year, longitude, latitude) %>%
mutate(yearInterval = cut_interval(year, length = 3))
# draw map by year
p <- ggplot() +
geom_sf(data = targetRegion) +
geom_point(data = data_combine, mapping = aes(x = longitude, y = latitude, group = birdTaxa, color = birdTaxa), shape = 15) +
# geom_point(data = data_combine %>% filter(birdTaxa == "八哥屬"), mapping = aes(x = longitude, y = latitude), color = "#ffff0060") +
facet_wrap(~yearInterval, nrow = 2) +
scale_fill_brewer() +
scale_color_manual(values = c("#ffff0040", "#0000ff60")) +
theme_classic() +
theme(axis.text.x = element_blank(),axis.text.y=element_blank(),
axis.line = element_blank(),axis.ticks = element_blank())
p
data_combine_taiwan <- bind_rows(data_monticola_clean, data_acridotheres_clean) %>%
select(birdTaxa, year, longitude, latitude) %>%
mutate(yearInterval = cut_interval(year, length = 2)) %>%
filter(longitude <= 122.5)
# draw map by year in Taiwan
targetRegion_taiwan <- world %>% filter(admin %in% c("Taiwan"))
p_taiwan <- ggplot() +
geom_sf(data = targetRegion_taiwan) +
geom_point(data = data_combine_taiwan, mapping = aes(x = longitude, y = latitude, group = birdTaxa, color = birdTaxa), shape = 15) +
# geom_point(data = data_combine %>% filter(birdTaxa == "八哥屬"), mapping = aes(x = longitude, y = latitude), color = "#ffff0060") +
facet_wrap(~yearInterval, nrow = 3) +
scale_fill_brewer() +
scale_color_manual(values = c("#ffff0020", "#0000ff60")) +
theme_classic() +
theme(axis.text.x = element_blank(),axis.text.y=element_blank(),
axis.line = element_blank(),axis.ticks = element_blank())
p_taiwan
於TBN網站以關鍵字”藍磯鶇”、“八哥屬”查找資料
dataTBN_monticola <- read_csv("data/tbn_monticola_20240922download/data.csv")
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 43571 Columns: 43
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (30): 紀錄識別號, 原始紀錄物種, 觀測方式, 外部識別碼, 行政區, 記錄者, 數量單位, 類群, 物種UUID, TaiCOL編碼,...
## dbl (9): 觀測年, 觀測月, 觀測日, 原始座標誤差(公尺), 緯度(十進位), 經度(十進位), 海拔, 個體數量, 數量...
## lgl (2): 保育類等級, 敏感資料模糊化程度
## dttm (1): 最後修改時間
## date (1): 觀測日期
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
dataTBN_acridotheres <- read_csv("data/tbn_acridotheres_202420922download/data.csv")
## Warning: One or more parsing issues, call `problems()` on your data frame for details,
## e.g.:
## dat <- vroom(...)
## problems(dat)
## Rows: 555806 Columns: 43
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## chr (31): 紀錄識別號, 原始紀錄物種, 觀測方式, 外部識別碼, 行政區, 記錄者, 數量單位, 類群, 物種UUID, TaiCOL編碼,...
## dbl (10): 觀測年, 觀測月, 觀測日, 原始座標誤差(公尺), 緯度(十進位), 經度(十進位), 海拔, 個體數量, 數量, 敏感資料模糊...
## dttm (1): 最後修改時間
## date (1): 觀測日期
##
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
利用 ggplot2 來繪製物種隨時間的分布圖。
# Summarize and prepare data for plotting
dataTBN_monticola_clean <- dataTBN_monticola %>%
drop_na(`緯度(十進位)`, `經度(十進位)`, 觀測日期) %>%
mutate(
year = year(觀測日期),
longitude = `經度(十進位)`,
latitude = `緯度(十進位)`
) %>%
filter(year >= 1970) %>%
mutate(birdTaxa = "藍磯鶇")
dataTBN_acridotheres_clean <- dataTBN_acridotheres %>%
drop_na(`緯度(十進位)`, `經度(十進位)`, 觀測日期) %>%
mutate(
year = year(觀測日期),
longitude = `經度(十進位)`,
latitude = `緯度(十進位)`
) %>%
filter(year >= 1970) %>%
mutate(birdTaxa = "八哥屬")
dataTBN_combine_taiwan <- bind_rows(dataTBN_monticola_clean, dataTBN_acridotheres_clean) %>%
select(birdTaxa, year, longitude, latitude) %>%
mutate(yearInterval = cut_interval(year, length = 5)) %>%
filter(longitude <= 122.5)
# draw map by year in Taiwan
targetRegion_taiwan <- world %>% filter(admin %in% c("Taiwan"))
p_TBN_taiwan <- ggplot() +
geom_sf(data = targetRegion_taiwan) +
geom_point(data = dataTBN_combine_taiwan, mapping = aes(x = longitude, y = latitude, group = birdTaxa, color = birdTaxa), shape = 15) +
# geom_point(data = data_combine %>% filter(birdTaxa == "八哥屬"), mapping = aes(x = longitude, y = latitude), color = "#ffff0060") +
facet_wrap(~yearInterval, nrow = 3) +
scale_fill_brewer() +
scale_color_manual(values = c("#ffff0020", "#0000ff60")) +
theme_classic() +
theme(axis.text.x = element_blank(),axis.text.y=element_blank(),
axis.line = element_blank(),axis.ticks = element_blank())
p_TBN_taiwan