서울시의 자치구를 지도로 나타냄
자치구에 생활체육시설 종류별로 지도에 색깔로 표현
각 자치구의 생활체육시설의 변화를 시계열로 나타냄.
shiny를 사용하여 각 자치구의 생활체육시설을 종류별로 지도에 크기로 표현
서울시 생활체육시설 현황 자료
http://data.seoul.go.kr/dataList/1391/S/2/datasetView.do#none에서 2010~2019년 자료를 다운로드 한 후,
위의 3행을 삭제하고, 숫자 컬럼의 ’,’를 모두 제거한 후 csv로 저장
GIS 한국 행정명에 따른 지도
http://www.gisdeveloper.co.kr/?p=2332 에서 ‘시군구’, ‘2021년 1월 업데이트 다운로드’
library(tidyverse) # dplyr, ggplot2 모두 포함
library(sf) # GIS 데이터 처리
df = read_csv("data/data.csv", locale=locale('ko',encoding='euc-kr'))
names(df)<-c('year', 'gu', 'tot_cnt', 'tot_area', 'yoteujang_cnt','yoteujang_area','ice_link_cnt','ice_link_area','jonghabcheyugsiseol_cnt', 'jonghabcheyugsiseol_area','swimming_pool_cnt','swimming_pool_area', 'cheyugdojang_cnt','cheyugdojang_area','golpeuyeonseubjang_cnt','golpeuyeonseubjang_area','fitness_cnt','fitness_area','billiard_cnt','billiard_area','sseolmaejang_cnt','sseolmaejang_area','mudojang_cnt','mudojang_area','mudohag-won_cnt','mudohag-won_area','golpeujang_cnt','golpeujang_area')
df[,3:28]<-df[,3:28] %>% sapply(as.integer) #har로 되어 있는 숫자 컬럼을 모두 숫자로(integer)로 변경
df$year <- as.character(df$year) # year 컬럼을 char로 변경
df <- df %>% filter(gu!='서울시') # 'gu'컬럼에 '서울시'는 모두 제거
df[is.na(df)]<-0 # na 값은 모두 0 값이므로 0으로 채움
서울시의 각 구별 지도를 불러오기 위해서는 ‘시군구’ 지도를 불러와야 한다.
GIS의 Shapefile을 읽어오는 방법이 sf 객체를 읽어오는 방법이 있고, sp 객체로 읽어오는 방법이 있는데,
sf 객체는 data frame의 형태로 읽어오고, sp는 S4 클라스로 읽어오는데, geom_sf를 사용하여 지도를 그리기에 편하므로 여기서는 sf 객체로 읽어와서 처리하겠다.
sig<-st_read('data', 'TL_SCCO_SIG')
Reading layer `TL_SCCO_SIG' from data source `C:\Rproject\seoul\data' using driver `ESRI Shapefile'
Simple feature collection with 250 features and 3 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: 746110.3 ymin: 1458754 xmax: 1387948 ymax: 2068444
projected CRS: PCS_ITRF2000_TM
sig$SIG_KOR_NM <- iconv(sig$SIG_KOR_NM, localeToCharset(), 'UTF-8') # 한글 처리
sig %>% filter(str_detect(SIG_KOR_NM, '구로구')) # 서울시의 'SIG_CD'를 알아내기 위해서
Simple feature collection with 1 feature and 3 fields
geometry type: MULTIPOLYGON
dimension: XY
bbox: xmin: 939273.8 ymin: 1941770 xmax: 947237.9 ymax: 1946679
projected CRS: PCS_ITRF2000_TM
SIG_CD SIG_ENG_NM SIG_KOR_NM geometry
1 11530 Guro-gu 구로구 MULTIPOLYGON (((945165.3 19...
seoul_sig <- sig %>%
filter(str_detect(SIG_CD, '11[0-9]{3}'))
서울시 지도 그려보기
seoul_sig %>%
ggplot()+
geom_sf(aes(fill=SIG_KOR_NM))+
geom_sf_text(aes(label=SIG_KOR_NM))+
theme(legend.position = 'none')
df_map <-
left_join(x = seoul_sig, y = df, by=c('SIG_KOR_NM'='gu'))
여기서는 2019년, 그리고 tot_cnt를 그렸다.
년도와 알고 싶은 생활체육시설을 바꿔가면서 그려볼 수 있다.
df_map %>%
filter(year=='2019') %>%
ggplot()+
geom_sf(aes(fill=SIG_KOR_NM))+
geom_sf_text(aes(label = paste0(SIG_KOR_NM,"\n","(",as.integer(tot_cnt),")")), size=3)+
theme(legend.position = 'none')+
labs(title = "서울시 각 구별 생활체육시설 총 개수")+
theme(plot.title = element_text(hjust = 0.5))
시계열 데이터는 지도를 그릴 필요가 없기 때문에 df데이터만 있으면 됨.
library(ggrepel) # For geom_text_repel instead of geom_text
df %>%
ggplot(aes(x = year, y = tot_cnt))+
geom_line(aes(color=gu, group=gu))+
geom_point(aes(color=gu))+
scale_y_log10(n.breaks=10)+
#scale_y_sqrt(n.breaks=10)+
labs(title = "서울시 각 구별 생활체육시설 총계(log 스케일임을 주의)")+
theme(plot.title = element_text(hjust = 0.5),legend.position = 'none')+
geom_text_repel(data=df %>% filter(year=='2010'),aes(label=gu, color=gu), size=2.5, hjust=1.2, vjust=0.1)
대화형으로 생활체육시설을 선택해서 그려보기 위해서 아래와 같이 shiny로 구현을 해 보았다.
그런데, 아쉽게도 여기 ‘rpub’ 사이트는 정적인 html만 지원하기 때문에 shiny 앱이 동작을 하지 않는다.
그래서 코드만 아래와 같이 적어 놓았다. 실제 Rstudio에서는 아래 그림과 같이 동작한다.
아래는 해당 코드이다
# library(shiny)
#
# shinyApp(
# ui = fluidPage(
# varSelectInput("variable", "Variable:", df[,3:28]), #데이터 프레임의 열 이름으로 선택 목록을 만듬. id, label, data. server의 !!input$variable
# plotOutput("data") # server의 output$data와 협력(co-work)
# ),
# server = function(input, output) {
# output$data <- renderPlot({
# ggplot(df, aes(x = year, y = !!input$variable))+ #y = tot_cnt -> y = !!input$variable
# geom_line(aes(color=gu, group=gu))+
# geom_point(aes(color=gu))+
# #scale_y_log10(n.breaks=10)+
# #scale_y_sqrt(n.breaks=10)+
# theme(legend.position = 'none')+
# geom_text_repel(data=df %>% filter(year=='2010'),
# aes(label=gu, color=gu),
# size=2.5, hjust=2.0, vjust=0.1)
# })
# }
#
# )