미세먼지 주범 석탄화력발전소, 대선 후보 입장은? 한겨례 신문 2017년 기사를 보면 석탄화력발전소에 대한 구체적인 정보가 담겨있다. World Resources Institute Global Power Plant Database 에서 전세계 화력발전소 중 한국만 추려 본다.
library(tidyverse)
library(reactable)
read_csv("data/globalpowerplantdatabasev120/global_power_plant_database.csv")
plant_df <-
plant_df %>%
plant_tbl <- 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)
st_read("data/map/HangJeongDong_ver20201001.geojson") korea_sf <-
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
korea_sf %>%
sido_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)
fromJSON("data/cancer_meta.json") %>% as.data.frame
cancer_meta <-
%>%
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
데이터를 다운로드 받아 대략적인 제공 데이터 형태를 살펴본다.
read_csv("data/건강보험심사평가원_암질환 평가 정보_20191031.csv", locale=locale('ko', encoding='euc-kr'))
cancer_df <-
%>%
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
cancer_df %>%
hospital_tbl <- 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 함수 --------------------------------------
function(query_address) {
get_lonlat <-
GET(url = 'https://dapi.kakao.com/v2/local/search/address.json',
daum_resp <-query = list(query = query_address),
add_headers(Authorization = paste0("KakaoAK ", Sys.getenv("DAUM_MAP_API_KEY"))))
daum_resp %>%
daum_list <- content(as = 'text') %>%
fromJSON()
daum_list$documents$road_address %>%
lon_lat <- select(lng = x, lat = y)
return(lon_lat)
}
safely(get_lonlat, otherwise = NA_real_)
safely_get_lonlat <-
cancer_df %>%
lung_df <- filter(평가항목 == "폐암")
map(lung_df$소재지, safely_get_lonlat)
geocoding_list <-
%>%
geocoding_list write_rds("data/geocoding_list.rds")
geocoding_list <- read_rds("data/geocoding_list.rds")
# 지오코딩 결과 저장 --------------------------------------
::jsonedit(geocoding_list) listviewer
중간에 결측값이 있어 이에 대한 보정 및 수정 작업을 수행한다.
tibble( lng = map(geocoding_list, "result") %>% map_chr(., "lng", .default = NA) %>% as.numeric,
lnglat_tbl <-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
폐암환자와 폐암환자 소재지 정보를 지오코딩한 결과를 결합시킨다.
cancer_df %>%
lung_df <- filter(평가항목 == "폐암")
lung_df %>%
lung_tbl <- 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)
st_read("data/map/HangJeongDong_ver20201001.geojson") korea_sf <-
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
makeIcon("Factory", "fig/noun_Factory_3373027.png", 37, 37)
powerplant <- makeIcon("Patient", "fig/noun_Patient_2071003.png", 37, 37)
patient <-
%>%
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