RでiNaturalistのデータをコロプレスマップで可視化する

今回はinaturalistのデータを可視化していきます。
以下のページが参考になったので、まずはこれと同じようにやっていきます。

https://note.com/ciel5/n/n24e2350af914

まずは必要なパッケージ・ライブラリをダウンロード。
```
#install.packages("rinat")
#install.packages("RCurl")

library(RCurl)
library(rinat)
library(sf)
library(tidyverse)
```

上述のサイトでは石川県のプロジェクトのデータを使っていましたが、全く同じは面白くないので、今回は大阪のデータを使用します。

https://www.inaturalist.org/projects/osaka-wildlife


```
#大阪のデータをスクレイピング
obs<-get_inat_obs_project("osaka-wildlife", type = "observations")
```

本当は20000データ以上ありましたが、サーバーの負荷を抑えるため一日10000データまでに制限されているみたいです。
列の量が非常に多くて扱いづらいので、列を絞ります。
```
obs_select<-obs %>% 
select(id,observed_on,latitude,longitude,species_guess,iconic_taxon_name,user_login,quality_grade,taxon_geoprivacy)

#次に使用する時のためにCSVに保存しておく
write.csv(obs_select,"data_osaka.csv")
```
分類別に集計してデータ数を見てみます。
```
#分類別のデータ数
obs_taxon<-obs_select %>%
  group_by(iconic_taxon_name) %>%
  summarize(count = n())　%>%
  as.data.frame()
obs_taxon

#分類別にデータ数をプロット
g_taxon <- ggplot(data=obs_select)+
  geom_bar(aes(x = iconic_taxon_name))
g_taxon 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635830/34678150-01d3-2624-27b8-6319ad1ffbbf.png)

```
#年の列を追加し、年毎に集計
YM<-substring(obs_select$observed_on,1,4)
obs_per_day<-obs_select %>%
  bind_cols(YM) %>%
  group_by(...10) %>%
  summarize(count = n())　%>%
  rename(year=...10) %>%
  as.data.frame()
  
g_year<-ggplot(data=obs_per_day,aes(x = year,y = count)) +
  geom_bar(stat = "identity")
g_year
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635830/06215852-56ba-0130-798e-193842847dcc.png)


```
#ユーザーで集計
obs_ID<-obs_select %>%
  group_by(user_login) %>%
  summarize(Number_of_observations = n()) %>%
  as.data.frame()
  
#ユーザー別データ数のヒストグラムを表示
g_ID <- ggplot(obs_ID, aes(x = Number_of_observations)) +
  geom_histogram()
g_ID
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635830/658392f4-715b-5ff3-31ed-253df7bf7479.png)

さあいよいよ地図にプロットしていきます。

```
#ポイントデータをGISデータにする
obs_shp<-st_as_sf(obs_select, coords = c("longitude", "latitude"), crs = 4326)

#CSVで保存したデータを読み込む場合
osaka_data<-read.csv("C:/Users/ユーザー名/Documents/作業ディレクトリ/data_osaka.csv")
obs_shp<-st_as_sf(osaka_data, coords = c("longitude", "latitude"), crs = 4326)
```

国土交通省のサイトから大阪の行政区域のデータをダウンロード。

https://nlftp.mlit.go.jp/ksj/gml/datalist/KsjTmplt-N03-2024.html


```
osaka<-st_read("C:/Users/ユーザー名/Documents/作業ディレクトリ/N03-20240101_27_GML/N03-20240101_27.shp")
```
まずは全データをプロット。
```
g_point_all<-ggplot() +
  geom_sf(data=osaka) +
  geom_sf(data=obs_shp)
g_point_all
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635830/c8c7e42b-3c8f-4bfb-b4d7-ba1024921ae8.png)

今度は位置情報が曖昧なデータを除いてプロット。

```
g_point_open<-ggplot() +
  geom_sf(data=osaka) +
  geom_sf(data=obs_shp %>% filter(taxon_geoprivacy != "obscured"))
g_point_open
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635830/56eedbb3-2425-6d38-2112-8e60456736ea.png)

分類別に色変えしてプロット。
```
g_point_open2<-ggplot() +
  geom_sf(data=osaka) +
  geom_sf(data=obs_shp %>% 
            filter(taxon_geoprivacy != "obscured"),aes(colour = iconic_taxon_name))
g_point_open2
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635830/47400852-fef1-ad5c-7163-aff81faff7ba.png)

とりあえずできました。ここまでは参考にしたサイトと同じです。
次にメッシュ毎にデータ数を集計してマッピングしていきます。

こちらのサイトが参考になりました。


https://ehime-wbsj.com/reports/2024/02/r_map_mesh_grid/


メッシュデータをダウンロードできるパッケージをダウンロードします。
```
install.packages("jpmesh") 
library(jpmesh) 
```

2次メッシュ（10km四方）のデータを作成します。
```
#大阪にしたいのでコードは27、メッシュサイズ(km)は10を指定
mesh10map <- administration_mesh(code = 27, to_mesh_size = 10) 
head(mesh10map)
```

メッシュデータとポイントデータの重なりを抽出します。
```
points_in_polygons <- st_join(obs_shp, mesh10map, join = st_within)
```
```
> points_in_polygons
Simple feature collection with 10000 features and 8 fields
Geometry type: POINT
Dimension:     XY
Bounding box:  xmin: 135.0343 ymin: 34.23758 xmax: 135.7996 ymax: 35.19845
Geodetic CRS:  WGS 84
First 10 features:
          id observed_on                species_guess iconic_taxon_name         user_login quality_grade
1  233032175  2024-08-01     fleabanes and horseweeds           Plantae          emil85738      needs_id
2  233033300  2024-07-31                     多疣壁虎          Reptilia             zirui1      research
3  233256192  2024-06-16        Japanese Boxer Mantis           Insecta            klearad      research
4  233355816  2023-04-06                Typical Blues           Insecta         claresoong      needs_id
5  233400577  2024-08-01                      Clytini           Insecta           zabukari      needs_id
6  233401158  2024-06-26                                       Animalia           zabukari      needs_id
7  233425805  2024-08-03 Serrognathus titanus pilifer           Insecta       thomasarendt      research
8  233456469  2024-08-03   Graphium sarpedon nipponum           Insecta gabriele_calabrese      research
9  233483216  2024-08-03                                        Insecta       midori_yaroo      needs_id
10 233487365  2024-08-03                                        Insecta       midori_yaroo      needs_id
   taxon_geoprivacy meshcode                  geometry
1              <NA>   523515 POINT (135.6311 34.83036)
2              open   513574 POINT (135.5768 34.63562)
3              <NA>   523523 POINT (135.4733 34.84915)
4              <NA>   523504 POINT (135.5227 34.68961)
5              <NA>   513542  POINT (135.2948 34.3994)
6              <NA>   513574 POINT (135.5194 34.61039)
7              <NA>   523525 POINT (135.6791 34.89276)
8              open   523504 POINT (135.5281 34.68449)
9              <NA>   513531 POINT (135.1815 34.31709)
10             <NA>   513531 POINT (135.1825 34.31937)
```
メッシュコードで集計します。
```
library(dplyr)
count_points <- points_in_polygons %>%
  group_by(meshcode) %>%
  summarise(count = n())
```
```
> count_points
   meshcode count                       geometry
1    513530     6 MULTIPOINT ((135.1044 34.28...
2    513531   170 MULTIPOINT ((135.1464 34.28...
3    513532    23 MULTIPOINT ((135.3024 34.32...
4    513533     6 MULTIPOINT ((135.4019 34.33...
5    513541   145 MULTIPOINT ((135.1827 34.33...
6    513542   203 MULTIPOINT ((135.2573 34.35...
7    513543   345 MULTIPOINT ((135.4063 34.37...
8    513544   856 MULTIPOINT ((135.522 34.379...
9    513545   102 MULTIPOINT ((135.668 34.403...
10   513551    15 MULTIPOINT ((135.2484 34.43...
11   513552     4 MULTIPOINT ((135.2993 34.43...
12   513553   143 MULTIPOINT ((135.38 34.4937...
13   513554   216 MULTIPOINT ((135.513 34.494...
14   513555   189 MULTIPOINT ((135.6341 34.45...
15   513562     3 MULTIPOINT ((135.2904 34.50...
16   513563   112 MULTIPOINT ((135.4346 34.54...
17   513564   265 MULTIPOINT ((135.5047 34.50...
18   513565    46 MULTIPOINT ((135.6411 34.57...
19   513573   387 MULTIPOINT ((135.4147 34.60...
20   513574   610 MULTIPOINT ((135.5443 34.59...
21   513575   214 MULTIPOINT ((135.6268 34.65...
22   523503   284 MULTIPOINT ((135.4998 34.72...
23   523504  1626 MULTIPOINT ((135.5582 34.67...
24   523505  1241 MULTIPOINT ((135.6969 34.74...
25   523513   130 MULTIPOINT ((135.4876 34.77...
26   523514   487 MULTIPOINT ((135.5797 34.75...
27   523515   574 MULTIPOINT ((135.7474 34.77...
28   523523   945 MULTIPOINT ((135.4529 34.91...
29   523524   221 MULTIPOINT ((135.5104 34.90...
30   523525   267 MULTIPOINT ((135.6332 34.91...
31   523532     4       POINT (135.3696 34.9728)
32   523533    34 MULTIPOINT ((135.4945 34.95...
33   523534    38 MULTIPOINT ((135.5754 34.98...
34   523535    17 MULTIPOINT ((135.6742 34.98...
35   523543     4 MULTIPOINT ((135.458 35.046...
36     <NA>    68 MULTIPOINT ((135.4384 35.19...
```

ジオメトリの列が2つあると結合時にエラーとなるので、一旦データフレーム化し、ジオメトリの列を削除します。
```
count_points<-as.data.frame(count_points)
kansatsu<-select(.data = count_points, -geometry)
```

mesh10mapと集計データを、メッシュ番号を基準に結合してkansatsu_meshを作ります。
```
kansatsu_mesh <- left_join(kansatsu,mesh10map,by = "meshcode")
kansatsu_mesh
```
```
> kansatsu_mesh
   meshcode count                       geometry
1    513530     6 POLYGON ((135 34.25, 135.12...
2    513531   170 POLYGON ((135.125 34.25, 13...
3    513532    23 POLYGON ((135.25 34.25, 135...
4    513533     6 POLYGON ((135.375 34.25, 13...
5    513541   145 POLYGON ((135.125 34.33333,...
6    513542   203 POLYGON ((135.25 34.33333, ...
```
いい感じです。グラフに描画します。
```
ggplot() + 
  geom_sf(data = osaka, fill = "white") +
  #mesh10mapのメッシュを描画。alpha=0で透過させ、線はグレー。
  geom_sf(data = mesh10map, alpha = 0, color = "grey") +
  #先ほど追加したメッシュ数の列のデータを基に色付け(fill)
  geom_sf(data=kansatsu_mesh,alpha = 0.8,aes(fill = count,geometry = geometry)) +  
  scale_fill_continuous(low = "yellow", high = "#009933")+
  #x軸の目盛りを調整
  scale_x_continuous(breaks=seq(135.0, 136,0.25))
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635830/d73a164d-9ced-9150-6acc-f3c794e80857.png)


今度は年別に分けたグラフを作成します。
```
#データに年の列を追加
points_in_polygons %>% 
  mutate(year=substring(observed_on,1,4))->
  points_in_polygons2
```
```
#メッシュコードと年で集計
count_points2 <- points_in_polygons2 %>%
  group_by(meshcode,year) %>%
  summarise(count = n())
```
```
#データフレーム化し、ジオメトリの列を削除
count_points2<-as.data.frame(count_points2)
kansatsu2<-select(.data = count_points2, -geometry)
```
```
#mesh10mapと集計データを、メッシュ番号を基準に結合してkansatsu_meshを作成。
kansatsu_mesh2 <- left_join(kansatsu2,mesh10map,by = "meshcode")
```
```
#年毎に分けた図をまとめて表示
ggplot() + 
  geom_sf(data = osaka, fill = "white") +
  geom_sf(data = mesh10map, alpha = 0, color = "grey") +
  geom_sf(data=kansatsu_mesh2,alpha = 0.8,aes(fill = count,geometry = geometry)) +  
  scale_fill_continuous(low = "yellow", high = "#009933")+
  scale_x_continuous(breaks=seq(135.0, 136,0.5))+
  facet_wrap(~ year, nrow = 3) +
  #凡例の位置を調整
  theme(legend.position = c( .8 , .15 )) 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635830/e56bbd4c-ec23-1dc6-3a53-0aa7db16edea.png)


今度は植生データと重ねあわせてみたいと思います。
環境省から5万分の1の植生図をダウンロードします。
2万5000分の1もありましたが、ダウンロード＆結合するシェープファイルが多すぎるのでやめました。

http://gis.biodic.go.jp/webgis/sc-025.html?kind=vg



```
#ダウンロードした植生データを読み込み
vg1<-st_read("C:/Users/ユーザー名/Documents/作業ディレクトリ/vg_27/vg_27/vg_27a.shp")
vg2<-st_read("C:/Users/ユーザー名/Documents/作業ディレクトリ/vg_27/vg3_27/vg3_27a.shp")
vg3<-st_read("C:/Users/ユーザー名/Documents/作業ディレクトリ/vg_27/vg4_27/vg4_27a.shp")
vg4<-st_read("C:/Users/ユーザー名/Documents/作業ディレクトリ/vg_27/vg5_27/vg5_27a.shp")
```
```
#ファイルを結合
osaka_vg<-rbind(vg1,vg2,vg3,vg4)
```
```
#メッシュデータとポイントデータの重なりを抽出
#結合のために座標系を変更
osaka_vg <- st_transform(osaka_vg, crs = 4326)
#結合
points_in_polygons3 <- st_join(obs_shp, osaka_vg, join = st_within)
points_in_polygons3
```
```
#データフレーム化し必要なデータを抽出
library(dplyr)
points_shyokusei <- points_in_polygons3 %>%
  as.data.frame() %>% 
  select(-geometry) %>% 
  filter(taxon_geoprivacy != "obscured")
```
```
#分類と植生で集計
points_shyokusei %>% 
  group_by(iconic_taxon_name,NAME) %>%
  summarise(count = n())->
  syukei_shyokusei
```
```
#植生別でデータ数を描画
syukei_shyokusei %>% 
  ggplot() +
  geom_bar(aes(x =NAME,y = count,fill=iconic_taxon_name),stat = "identity") +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1,size=7))+
  labs(x = "植生") 
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3635830/f2a08e7c-e335-e25e-666f-00c4ebb4927d.png)

市街地、公園、開放水域の順にデータが多くなってますね。
水田でのデータもそこそこ。
大阪だと大都会のイメージですが、郊外は田畑も広がっているのでデータが上がっているのかもです。