미세먼지 주범 석탄화력발전소, 대선 후보 입장은? 한겨례 신문 2017년 기사를 보면 석탄화력발전소에 대한 구체적인 정보가 담겨있다. World Resources Institute Global Power Plant Database 에서 전세계 화력발전소 중 한국만 추려 본다.
library(tidyverse)
library(reactable)
plant_df <- read_csv("data/globalpowerplantdatabasev120/global_power_plant_database.csv")
plant_tbl <- plant_df %>%
filter(country == "KOR") %>%
select("name", "capacity_mw", "latitude", "longitude", fuel = "primary_fuel", year = "commissioning_year", "owner", "url",
generation_gwh = "estimated_generation_gwh")
plant_tbl %>%
reactable::reactable()석탄 발전소만 추려 지도에 시각화 시켜보자.
library(glue)
library(leaflet)
plant_tbl %>%
filter(fuel == "Coal") %>%
leaflet() %>%
addProviderTiles(provider = providers$OpenStreetMap) %>%
addMarkers(lng=~longitude, lat = ~latitude, clusterOptions = markerClusterOptions(),
popup = ~ as.character(glue("<strong> {name} </strong> <br>
· 회사: {owner}<br>
· 용량: {scales::comma(capacity_mw, accuracy = 1) } MW<br>
· 발전: {scales::comma(generation_gwh, accuracy = 1)} GWh<br>
· 연료: {fuel}")))석탄 발전소 용량을 기준으로 시도 경계를 추가하여 가시성을 높여보자.
library(sf)
korea_sf <- st_read("data/map/HangJeongDong_ver20201001.geojson")Reading layer `1' from data source `C:\docs\esg\data\map\HangJeongDong_ver20201001.geojson' using driver `GeoJSON'
Simple feature collection with 3492 features and 8 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 124.6097 ymin: 33.11187 xmax: 131.8713 ymax: 38.61695
Geodetic CRS: WGS 84
sido_sf <- korea_sf %>%
group_by(sido, sidonm) %>%
summarise(cnt = n()) %>%
ungroup() %>%
select(-cnt)
plant_tbl %>%
filter(fuel == "Coal") %>%
leaflet() %>%
## 석탄 화력 발전소 위치 --------------------------------------
addProviderTiles(provider = providers$OpenStreetMap) %>%
addMarkers(lng=~longitude, lat = ~latitude, clusterOptions = markerClusterOptions(),
popup = ~ as.character(glue("<strong> {name} </strong> <br>
· 회사: {owner}<br>
· 용량: {scales::comma(capacity_mw, accuracy = 1) } MW<br>
· 발전: {scales::comma(generation_gwh, accuracy = 1)} GWh<br>
· 연료: {fuel}"))) %>%
addCircleMarkers( radius = ~ (capacity_mw)^(1/2),
stroke = FALSE, fillOpacity = 0.5) %>%
## 시도 경계 shapefile --------------------------------------
addPolygons(data = sido_sf, opacity = 1.0, fillOpacity = 0.1,
weight = 1,
highlightOptions = highlightOptions(color = "black", weight = 3, bringToFront = TRUE),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto"))추정 발전량을 기준으로 시도 경계를 포함시켜 지도 위에 시각화를 해 보자.
plant_tbl %>%
filter(fuel == "Coal") %>%
leaflet() %>%
## 석탄 화력 발전소 위치 --------------------------------------
addProviderTiles(provider = providers$OpenStreetMap) %>%
addMarkers(lng=~longitude, lat = ~latitude, clusterOptions = markerClusterOptions(),
popup = ~ as.character(glue("<strong> {name} </strong> <br>
· 회사: {owner}<br>
· 용량: {scales::comma(capacity_mw, accuracy = 1) } MW<br>
· 발전: {scales::comma(generation_gwh, accuracy = 1)} GWh<br>
· 연료: {fuel}"))) %>%
addCircleMarkers( radius = ~ (generation_gwh)^(1/3),
stroke = FALSE, fillOpacity = 0.5) %>%
## 시도 경계 shapefile --------------------------------------
addPolygons(data = sido_sf, opacity = 1.0, fillOpacity = 0.1,
weight = 1,
highlightOptions = highlightOptions(color = "black", weight = 3, bringToFront = TRUE),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto"))건강보험심사평가원 암질환 평가 정보에서 데이터를 다운로드 받아 준비한다.
library(jsonlite)
cancer_meta <- fromJSON("data/cancer_meta.json") %>% as.data.frame
cancer_meta %>%
pivot_longer(cols = everything(), names_to = "항목", values_to = "상세정보")# A tibble: 15 x 2
항목 상세정보
<chr> <chr>
1 name 건강보험심사평가원_암질환 평가 정보
2 description 평가수행항목: 간암, 대장암, 위암, 유방암, 폐암 / 평가결과는 5개 등급으로 나누어 공개(~
3 url https://www.data.go.kr/data/15052118/fileData.do
4 keywords 병원평가,암질환,건강보험
5 license https://data.go.kr/ugs/selectPortalPolicyView.do
6 creator.name 건강보험심사평가원
7 creator.contactPoint.c~ 빅데이터실 빅데이터전략부
8 creator.contactPoint.t~ +82-0337391047
9 creator.contactPoint..~ ContactPoint
10 creator..type Organization
11 distribution.encodingF~ CSV
12 distribution.contentUrl https://www.data.go.kr/cmm/cmm/fileDownload.do?atchF~
13 distribution..type DataDownload
14 X.context https://schema.org
15 X.type Dataset
데이터를 다운로드 받아 대략적인 제공 데이터 형태를 살펴본다.
cancer_df <- read_csv("data/건강보험심사평가원_암질환 평가 정보_20191031.csv", locale=locale('ko', encoding='euc-kr'))
cancer_df %>%
reactable(columns = list(
병원명 = colDef(name = "병원명", minWidth = 120),
평가항목 = colDef(name = "평가항목", minWidth = 50),
평가등급 = colDef(name = "평가등급", minWidth = 50),
소재지 = colDef(name = "소재지", minWidth = 210)
))환자별 암질환 정보를 살펴보자.
cancer_df %>%
count(평가항목, name = "환자수", sort = TRUE) %>%
mutate(비율 = 환자수 / sum(환자수) * 100)# A tibble: 4 x 3
평가항목 환자수 비율
<chr> <int> <dbl>
1 대장암 230 31.2
2 위암 204 27.7
3 유방암 183 24.9
4 폐암 119 16.2
hospital_tbl <- cancer_df %>%
filter(평가항목 == "폐암") %>%
mutate(병원명칭 = case_when(
str_detect(병원명, "가톨릭") ~ "가톨릭",
str_detect(병원명, "고려대") ~ "고려대",
str_detect(병원명, "순천향") ~ "순천향",
str_detect(병원명, "효신") ~ "효신",
str_detect(병원명, "경희") ~ "경희",
str_detect(병원명, "삼성") ~ "삼성",
str_detect(병원명, "서울대") ~ "서울대",
str_detect(병원명, "연세") ~ "연세",
str_detect(병원명, "인제") ~ "인제",
str_detect(병원명, "한림") ~ "한림",
str_detect(병원명, "한양") ~ "한양",
str_detect(병원명, "국립") ~ "국립암",
TRUE ~ 병원명)) %>%
count(병원명칭, sort = TRUE)
hospital_tbl # A tibble: 89 x 2
병원명칭 n
<chr> <int>
1 가톨릭 10
2 인제 5
3 한림 5
4 순천향 4
5 고려대 3
6 삼성 3
7 연세 3
8 경희 2
9 국립암 2
10 서울대 2
# ... with 79 more rows
다음 카카오 API를 사용해서 주소정보를 제공하고 위경도를 받아온다.
library(httr)
# geocoding 함수 --------------------------------------
get_lonlat <- function(query_address) {
daum_resp <- GET(url = 'https://dapi.kakao.com/v2/local/search/address.json',
query = list(query = query_address),
add_headers(Authorization = paste0("KakaoAK ", Sys.getenv("DAUM_MAP_API_KEY"))))
daum_list <- daum_resp %>%
content(as = 'text') %>%
fromJSON()
lon_lat <- daum_list$documents$road_address %>%
select(lng = x, lat = y)
return(lon_lat)
}
safely_get_lonlat <- safely(get_lonlat, otherwise = NA_real_)
lung_df <- cancer_df %>%
filter(평가항목 == "폐암")
geocoding_list <- map(lung_df$소재지, safely_get_lonlat)
geocoding_list %>%
write_rds("data/geocoding_list.rds")geocoding_list <-
read_rds("data/geocoding_list.rds")
# 지오코딩 결과 저장 --------------------------------------
listviewer::jsonedit(geocoding_list)중간에 결측값이 있어 이에 대한 보정 및 수정 작업을 수행한다.
lnglat_tbl <- tibble( lng = map(geocoding_list, "result") %>% map_chr(., "lng", .default = NA) %>% as.numeric,
lat = map(geocoding_list, "result") %>% map_chr(., "lat", .default = NA) %>% as.numeric)
lnglat_tbl# A tibble: 119 x 2
lng lat
<dbl> <dbl>
1 127. 37.5
2 127. 37.3
3 127. 37.5
4 127. 37.6
5 127. 37.5
6 127. 37.8
7 127. 37.5
8 127. 37.6
9 129. 37.8
10 127. 37.6
# ... with 109 more rows
폐암환자와 폐암환자 소재지 정보를 지오코딩한 결과를 결합시킨다.
lung_df <- cancer_df %>%
filter(평가항목 == "폐암")
lung_tbl <- lung_df %>%
bind_cols(lnglat_tbl)library(glue)
library(leaflet)
lung_tbl %>%
leaflet() %>%
addProviderTiles(provider = providers$OpenStreetMap) %>%
addMarkers(lng=~lng, lat = ~lat, clusterOptions = markerClusterOptions(),
popup = ~ as.character(glue("<strong> {병원명} </strong> <br>
· 평가항목: {평가항목}<br>
· 평가등급: {평가등급} <br>
· 소재지: {소재지 }")))석탄 발전소 위치와 폐암 환자 위치를 함께 지도위에 시각화 시킨다.
library(sf)
korea_sf <- st_read("data/map/HangJeongDong_ver20201001.geojson")Reading layer `1' from data source `C:\docs\esg\data\map\HangJeongDong_ver20201001.geojson' using driver `GeoJSON'
Simple feature collection with 3492 features and 8 fields
Geometry type: MULTIPOLYGON
Dimension: XY
Bounding box: xmin: 124.6097 ymin: 33.11187 xmax: 131.8713 ymax: 38.61695
Geodetic CRS: WGS 84
powerplant <- makeIcon("Factory", "fig/noun_Factory_3373027.png", 37, 37)
patient <- makeIcon("Patient", "fig/noun_Patient_2071003.png", 37, 37)
plant_tbl %>%
filter(fuel == "Coal") %>%
leaflet() %>%
## 석탄 화력 발전소 위치 --------------------------------------
addProviderTiles(provider = providers$OpenStreetMap) %>%
addMarkers(lng=~longitude, lat = ~latitude, clusterOptions = markerClusterOptions(),
icon=powerplant,
popup = ~ as.character(glue("<strong> {name} </strong> <br>
· 회사: {owner}<br>
· 용량: {scales::comma(capacity_mw, accuracy = 1) } MW<br>
· 발전: {scales::comma(generation_gwh, accuracy = 1)} GWh<br>
· 연료: {fuel}"))) %>%
addCircleMarkers( radius = ~ (capacity_mw)^(1/2),
stroke = FALSE, fillOpacity = 0.5) %>%
## 시도 경계 shapefile --------------------------------------
addPolygons( data = sido_sf, opacity = 1.0, fillOpacity = 0.1,
weight = 1,
highlightOptions = highlightOptions(color = "black", weight = 3, bringToFront = TRUE),
labelOptions = labelOptions(
style = list("font-weight" = "normal", padding = "3px 8px"),
textsize = "15px",
direction = "auto")) %>%
addMarkers( data = lung_tbl, lng=~lng, lat = ~lat, icon = patient,
popup = ~ as.character(glue("<strong> {병원명} </strong> <br>
· 평가항목: {평가항목}<br>
· 평가등급: {평가등급} <br>
· 소재지: {소재지 }")))데이터 과학자 이광춘 저작
kwangchun.lee.7@gmail.com