Last active
November 10, 2023 10:34
-
-
Save practice/0cf8d2eaad03f6d878f6bea371d1769e to your computer and use it in GitHub Desktop.
통계 기법 지상 측정 기반 분포 지도 (농도, 오차)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
################(1) 패키지 및 자료 불러오기######################## | |
install.packages('maptools'); | |
install.packages('rgdal'); | |
install.packages('sp'); | |
install.packages('tmap'); | |
install.packages('gstat'); | |
install.packages('raster'); | |
install.packages('rgeos'); | |
install.packages('dplyr'); | |
install.packages('caret'); | |
library('maptools'); | |
library('rgdal'); | |
library('sp'); | |
library('tmap'); | |
library('gstat'); | |
library('raster'); | |
library('rgeos'); | |
library('dplyr'); | |
library('caret') | |
setwd("~/GroundPM2.5_Asia"); | |
# 데이터 파일을 불러오는 코드입니다. | |
# ‘예시_한국/중국‘ 파일은 실제로 측정소 농도 자료가 실시간으로 들어오면 해당 파일로 넣으시면 됩니다. | |
# ’측정소좌표_한국/중국’ 파일은 최신 측정소 정보(위치 및 측정소명) 업데이트한이므로 제가 드린 파일로 계속 사용하시면 됩니다. | |
data_KR <- read.csv("예시_한국.csv", fileEncoding="CP949") | |
location_KR <- read.csv("측정소좌표_한국.csv", fileEncoding="CP949") | |
data_CN <- read.csv("예시_중국.csv", fileEncoding="CP949") | |
location_CN <- read.csv("측정소좌표_중국.csv", fileEncoding="CP949") | |
# 실시간 농도 자료+측정소 정보(좌표, 이름) 결합 코드 | |
PM_KR <- merge(data_KR, location_KR, by="측정소명") | |
PM_CN <- merge(data_CN, location_CN, by="측정소명") | |
# 한국 자료, 중국 자료 결합 코드 | |
PM <- rbind(PM_KR, PM_CN) | |
# raw data 백업용 | |
PMraw <- PM | |
# 결측자료나, 가끔씩 중국 자료에서 결측값이 다르게 표시(예: NaN)으로 되어있을 때, 처리하는 코드입니다. | |
# NaN 부분은 상황에 맞게 수정하면 됩니다. | |
PM <- PM[!(PM$PM25 == "NaN"),] | |
PM <- na.omit(PM) | |
# 오차 계산에 필요한 raw data | |
PM_err <- PM | |
################(2) 지상관측기반 농도지도 작성 및 그리드별 농도 저장######################## | |
# 분포지도 작성에 필요한 동아시아 지도 및 적용반경 shp 파일 불러오기입니다. | |
# 제가 새로 보내드린 GroundPM2.5_Asia 폴더 안 GIS 폴더 안에 있는 파일 그대로 사용하시면 됩니다. | |
CRS_WGS <- CRS("+proj=longlat +datum=WGS84") | |
EastAsia <- readShapePoly("GIS/EastAsia.shp") | |
buffer <- readShapePoly("GIS/buf_KrCh.shp") | |
# 동아시아, 적용반경, 지상 관측자료의 GIS 그림을 위한 좌표설정 코드 | |
proj4string(EastAsia) <- CRS("+proj=longlat +datum=WGS84") | |
proj4string(buffer) <- CRS("+proj=longlat +datum=WGS84") | |
coordinates(PM) <- ~lon+lat | |
proj4string(PM) <- CRS("+proj=longlat +datum=WGS84") | |
# 보간법 계산에 필요한 grid 생성 코드 | |
grid <- as.data.frame(spsample(EastAsia, "regular", n=50000)); | |
grid_extract <- as.data.frame(spsample(EastAsia, "regular", n=50000)); | |
names(grid) <- c("lon", "lat"); | |
coordinates(grid) <- c("lon", "lat"); | |
gridded(grid) <- TRUE; | |
fullgrid(grid) <- TRUE; | |
# 좌표계 통일 | |
proj4string(grid) <- proj4string(PM); | |
# IDW 보간법 적용(분포지도 작성) | |
data.idw <- gstat::idw(PM25~1, PM, newdata=grid, idp=2.0); | |
data.raster <- raster(data.idw); | |
# 동아시아 크기에 맞게 자른 후, 적용 반경안에 농도만 자르는 코드 | |
PMplot <- mask(data.raster, buffer); | |
PMplot2 <- mask(PMplot, EastAsia); | |
PMconc <- extract(PMplot2, grid_extract) | |
Extract_PM_conc <- cbind(grid_extract, PMconc) | |
names(Extract_PM_conc) <- c('lat', 'lon', 'PM25conc') | |
# 지상관측 기반 농도분포지도의 grid 별 농도값을 csv 파일로 저장하는 코드입니다. “ ” 사이에 원하시는 파일명으로 수정가능합니다. | |
write.csv(Extract_PM_conc,"Ground observ_conc_EA.csv") | |
################(3) 지상관측기반 오차지도 작성 및 그리드별 농도 저장######################## | |
# 오차 계산을 위해 무작위로 지상 측정소 자료를 7:3으로 나누는 코드입니다. | |
div <- createDataPartition(PM_err$PM25, p=0.7, list=F) | |
Sample <- PM_err[div,] | |
Val <- PM_err[-div,] | |
Sample_0 <- Sample | |
Val_0 <- Val | |
# 나눠진 Sample 측정소와 Validation 측정소 자료에 대한 좌표계 설정 | |
coordinates(Sample) <- ~lon+lat | |
proj4string(Sample) <- CRS("+proj=longlat +datum=WGS84") | |
coordinates(Val) <- ~lon+lat | |
proj4string(Val) <- CRS("+proj=longlat +datum=WGS84") | |
# 오차지도를 작성하기 위한 grid 생성 코드 | |
grid_error <- as.data.frame(spsample(EastAsia, "regular", n=50000)); | |
names(grid_error) <- c("lon", "lat"); | |
coordinates(grid_error) <- c("lon", "lat"); | |
gridded(grid_error) <- TRUE; | |
fullgrid(grid_error) <- TRUE; | |
# 좌표계 통일 | |
proj4string(grid_error) <- proj4string(Sample); | |
proj4string(grid_error) <- proj4string(Val); | |
# Sample 측정소의 IDW 적용을 통한 분포지도 작성 | |
Sam.idw <- gstat::idw(PM25~1, Sample, newdata=grid_error, idp=2.0); | |
Sam.raster <- raster(Sam.idw); | |
# Validation 측정소 지점에서 측정값과 Sample 측정소 자료로 예측한 예측값을 비교하여 오차(Error) 계산 | |
Sam.pre <- extract(Sam.raster, Val) | |
Error <- cbind(Val_0, Sam.pre) | |
Ground_err <- data.frame(abs(Error$PM25-Error$Sam.pre)) | |
names(Ground_err) <- c('PM25err') | |
Ground_err <- cbind(Error, Ground_err) | |
# 오차 자료 백업 | |
Ground_err0 <- Ground_err | |
# 계산된 오차 농도 자료에 좌표계 설정 | |
coordinates(Ground_err) <- ~lon+lat | |
proj4string(Ground_err) <- CRS("+proj=longlat +datum=WGS84") | |
proj4string(grid_error) <- proj4string(Ground_err); | |
# 오차 농도로 오차지도 작성 | |
error.idw <- gstat::idw(PM25err~1, Ground_err, newdata=grid_error, idp=2.0); | |
error.raster <- raster(error.idw); | |
# 오차지도에 동아시아 크기로 자르고, 적용 반경안에 농도만 자르는 코드 | |
PMerr <- mask(error.raster, buffer); | |
PMerr2 <- mask(PMerr, EastAsia); | |
PMerror <- extract(PMerr2, grid_extract) | |
Extract_PM_err <- cbind(grid_extract, PMerror) | |
names(Extract_PM_err) <- c('lat', 'lon', 'PM25err') | |
# 지상관측 오차 분포지도의 grid 별 농도값을 csv 파일로 저장하는 코드입니다. “ ” 사이에 원하시는 파일명으로 수정가능합니다. | |
write.csv(Extract_PM_err,"Ground observ_error_EA.csv") | |
################(4) 지상관측기반 농도 및 오차지도 저장######################## | |
# 농도분포지도 그리기 | |
tm_shape(EastAsia)+tm_polygons(alpha=0)+tm_shape(PMplot2)+tm_raster(n=30, style="fixed", breaks=c(0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 90, 100, 110, 120, 500), | |
palette=c("mediumblue", "blue", "deepskyblue2", "cyan", "green", "greenyellow", "yellow", "gold", "orange2", "darkorange2", "red", "red2", "red3", "orangered4", "red4", "coral4", "black"), legend.reverse=TRUE, | |
title = "PM2.5 conc. (ug/m3)")+tm_shape(EastAsia)+tm_polygons(alpha=0)+tm_legend(legend.outside=TRUE, legend.title.size=2, legend.text.size=1.5); | |
# 오차분포지도 그리기 | |
tm_shape(EastAsia)+tm_polygons(alpha=0)+tm_shape(PMerr2)+tm_raster(n=30, style="fixed", breaks=c(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 500), | |
palette=c("mediumblue", "blue", "deepskyblue2", "cyan", "green", "greenyellow", "yellow", "gold", "orange2", "darkorange2", "red", "red2", "red3", "orangered4", "red4", "coral4", "black"), legend.reverse=TRUE, | |
title = "PM2.5 error. (ug/m3)")+tm_shape(EastAsia)+tm_polygons(alpha=0)+tm_legend(legend.outside=TRUE, legend.title.size=2, legend.text.size=1.5); | |
PMmap_conc <- tm_shape(EastAsia)+tm_polygons(alpha=0)+tm_shape(PMplot2)+tm_raster(n=30, style="fixed", breaks=c(0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 90, 100, 110, 120, 500), | |
palette=c("mediumblue", "blue", "deepskyblue2", "cyan", "green", "greenyellow", "yellow", "gold", "orange2", "darkorange2", "red", "red2", "red3", "orangered4", "red4", "coral4", "black"), legend.reverse=TRUE, | |
title = "PM2.5 conc. (ug/m3)")+tm_shape(EastAsia)+tm_polygons(alpha=0)+tm_legend(legend.outside=TRUE, legend.title.size=2, legend.text.size=1.5); | |
PMmap_error <- tm_shape(EastAsia)+tm_polygons(alpha=0)+tm_shape(PMerr2)+tm_raster(n=30, style="fixed", breaks=c(0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 500), | |
palette=c("mediumblue", "blue", "deepskyblue2", "cyan", "green", "greenyellow", "yellow", "gold", "orange2", "darkorange2", "red", "red2", "red3", "orangered4", "red4", "coral4", "black"), legend.reverse=TRUE, | |
title = "PM2.5 error. (ug/m3)")+tm_shape(EastAsia)+tm_polygons(alpha=0)+tm_legend(legend.outside=TRUE, legend.title.size=2, legend.text.size=1.5); | |
tmap_save(PMmap_conc, width=20, height=20, units="cm", dpi=300, filename="PMmap_conc.png") | |
tmap_save(PMmap_error, width=20, height=20, units="cm", dpi=300, filename="PMmap_error.png") | |
Author
practice
commented
Nov 10, 2023
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment