2022年11月21日月曜日

面積を定量化

午前
・標本整理

午後
・データ解析
・会議

昨年からの悩みが、多少解決した。ただし、根本的な問題は解決できていない。

とある昆虫の砂丘内の分布データ。この分布の変化を定量的に評価したい、というのが昨年来の課題。
で例えば、geom_density_2d()を使ってカーネル密度推定を表示したり、
ggdensity::geom_hdr()を使ってhighest density regions (HDRs)を表示したり、
ggalt::geom_encircle()を使って輪郭を表示できることが分かった。
しかし、これらの面積を定量化する方法が分からなかった。

そこで、スマートな方法は諦めて、面積内を特定の色で塗りつぶして、そのピクセル数を計測する方法にたどり着いた。それはそれで面倒だったのだが、colorfindr::get_colors()というとても便利な方法を知った。

普通の散布図なら、グラフに使用していない色で塗りつぶせば良いのだが、上記のように地図上に描いている場合は、輪郭だけの図を作成した方が無難だろうと考えた。

その場合、地図の代わりに、空のラスタを準備して、そこに(例えば)黒色で塗りつぶした図を描く。

ちなみに、colorfindr::get_colors()は、一度、画像として保存して読み込まないと使えない(?)みたい。

プロットデータは、sf形式、平面直角座標のpointデータで、「Bn_2021_JGD2011」に入っているとする。
#枠となるラスタの作成
library(raster)
library(sf)
e <- raster::extent(-11000, -7000, -52500, -49500) #平面直角座標
sp_e <- as(e, "SpatialPolygons") #sp形式に変更
sf_e <- st_as_sf(sp_e) #sf形式に変更
st_crs(sf_e) <- "+proj=tmerc +lat_0=36 +lon_0=134.333333333333
		+k=0.9999 +x_0=0 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0
		+units=m +no_defs +type=crs" #JGD2011;平面直角座標

#get_colors()は画像として一度保存する必要がある!
library(ggplot2)
png("Area_karnel.png", height=3000, width=3000)
ggplot() +
 	geom_density_2d_filled(aes(x=st_coordinates(Bn_2021_JGD2011)[,1],
  		y=st_coordinates(Bn_2021_JGD2011)[,2]), linewidth=0, col="white") +
	scale_fill_manual(values = c("white", "black", "black", "black", "black", "black", "black", "black")) +
	scale_x_continuous(limits = c(-11000, -7000)) +
 	scale_y_continuous(limits = c(-52500, -49500)) +
 	theme(panel.background = element_blank(), #背景を透明にする
		plot.background = element_blank(), #背景を透明にする
 		panel.grid.major = element_blank(), #グラフの線;邪魔なので白で消す
 		panel.border = element_blank(), #グラフの線;邪魔なので白で消す
		axis.title = element_blank(),
 		axis.text = element_blank(),
		axis.ticks = element_blank(), 
 		legend.position = 'none')
dev.off()
二値化の画像ができる。上記のカーネル密度推定は時計周りに回転させて、トリミングしているので一見異なるが、同じデータで作図している。
これを読み込んで、下記のようにget_colors()を実行すると、各色のピクセル数を計測できる。白と黒しかないのだが、他にもいくつか計測される、、、ごく僅か(ほとんど1ピクセル)なので無視して大丈夫だと思う。
library(colorfindr)
get_colors("Area_Bn_2021_karnel.png") #各色のピクセル数
これで算出できるのは、画像内の各色のピクセル数なので、比較する場合は、同じ大きさの画像で比較する必要がある。

(試していないが)面積そのものを計測したい場合は、例えば、100m2の方形区を作成して、そのピクセル数を基に計算すれば良さそう。

ただ、そもそも動物の分布を適切に表現できていないので、意味がないことも分かった。