(주차장에) 제 자리 있나요?

feat. 서울시설공단 공영주차장 잔여주차 가능 대수

브런치 글 [생활 속 데이터분석] (주차장에) 제 자리 있나요? https://brunch.co.kr/@llun/23의 코드입니다.
브런치 플랫폼상 코드 복사가 안 되고 하이라이트 기능이 없는 한계가 있어 마크다운으로 제공합니다.

웹 크롤링

# URL을 통해 가져옴
content <- GET("https://www.sisul.or.kr/open_content/parking/guidance/useable.jsp")

# 셀 내용 읽어오기 - 파이프를 이용하여 한번에 연결
useable_df <- read_html(content) %>%
  html_nodes("table tr td") %>%
  html_text() %>%
  matrix(ncol = 4, byrow = TRUE) %>% 
  as.data.frame()

# 열 이름(colnames)도 가져와보자
colnames(useable_df) <- read_html(content) %>% html_nodes("table tr th") %>% html_text()

# 현재시간(크롤링 시각) 추가 & datetime이라는 이름의 시각 열을 추가
useable_df$datetime <- format(Sys.time(), tz="Asia/Seoul", usetz=TRUE)

# 크롤링 작업한 데이터 확인
kable(useable_df)
번호 주차장명 주차면수 잔여주차가능대수 datetime
1 잠실역 357 305 2019-08-18 05:05:55 KST
2 구로디지털단지역 92 57 2019-08-18 05:05:55 KST
3 개화산역 322 251 2019-08-18 05:05:55 KST
4 수서역북 570 471 2019-08-18 05:05:55 KST
5 수서역남 22 20 2019-08-18 05:05:55 KST
6 복정역 363 312 2019-08-18 05:05:55 KST
7 한강진역 176 144 2019-08-18 05:05:55 KST
8 수락산역 157 108 2019-08-18 05:05:55 KST
9 화랑대역 332 277 2019-08-18 05:05:55 KST
10 구파발역 399 348 2019-08-18 05:05:55 KST
11 신설동공영 79 3 2019-08-18 05:05:55 KST
12 영등포구청역 137 74 2019-08-18 05:05:55 KST
13 적선노외 600 591 2019-08-18 05:05:55 KST
14 학여울역 180 122 2019-08-18 05:05:55 KST
15 사당노외 184 102 2019-08-18 05:05:55 KST
16 종묘 1316 1259 2019-08-18 05:05:55 KST
17 천왕역 328 239 2019-08-18 05:05:55 KST
18 개화역 483 383 2019-08-18 05:05:55 KST
19 마포유수지 505 402 2019-08-18 05:05:55 KST
20 세종로 1260 1139 2019-08-18 05:05:55 KST
21 신대방역 60 18 2019-08-18 05:05:55 KST
22 동대문 1092 1056 2019-08-18 05:05:55 KST
23 천호역 1430 860 2019-08-18 05:05:55 KST
24 용산주차빌딩 561 411 2019-08-18 05:05:55 KST
25 신천유수지 221 174 2019-08-18 05:05:55 KST
26 서울역관광버스주차장 33 35 2019-08-18 05:05:55 KST
27 신방화역 199 132 2019-08-18 05:05:55 KST
28 훈련원공원 873 1038 2019-08-18 05:05:55 KST
29 가양라이품 38 34 2019-08-18 05:05:55 KST
30 흑석동공영 107 81 2019-08-18 05:05:55 KST
31 웃우물공영 39 30 2019-08-18 05:05:55 KST
32 장안2동 39 10 2019-08-18 05:05:55 KST

When you click the Knit button a document will be generated that includes both content as well as the output of any embedded R code chunks within the document. You can embed an R code chunk like this:

# 데이터를 불러올 수 있는 다양한 방법

# useable_df <- read_excel("~/R/useable_df.xlsx")

# useable_df <- read_csv("번호,주차장명,주차면수,잔여주차가능대수
# 1,잠실역,357,305
# 2,구로디지털단지역,92,51
# 3,개화산역,322,258
# 4,수서역북,570,467
# 5,수서역남,22,20
# 6,복정역,363,315
# 7,한강진역,176,138
# 8,수락산역,157,108
# 9,화랑대역,332,275
# 10,구파발역,399,348
# 11,신설동공영,79,3
# 12,영등포구청역,137,74
# 13,적선노외,600,591
# 14,학여울역,180,121
# 15,사당노외,184,98
# 16,종묘,1316,1260
# 17,천왕역,328,240
# 18,개화역,483,387
# 19,마포유수지,505,403
# 20,세종로,1260,1139
# 21,신대방역,60,18
# 22,동대문,1092,1053
# 23,천호역,1430,841
# 24,용산주차빌딩,561,411
# 25,신천유수지,221,175
# 26,서울역관광버스주차장,33,35
# 27,신방화역,199,131
# 28,훈련원공원,873,1037
# 29,가양라이품,38,35
# 30,흑석동공영,107,80
# 31,웃우물공영,39,31
# 32,장안2동,39,10")
# 에러 발생
try(gvisColumnChart(useable_df %>% select(`주차면수`, `잔여주차가능대수`)))
## Error in gvisCheckCoreChartData(data, xvar = xvar, yvar = yvar) : 
##   Error: Your data has to have at least one numerical column.

데이터가 숫자 형태가 아니라며 에러가 나네요. str() 함수로 살펴보니 factor형입니다.

# 데이터 구조(structure) 확인
str(useable_df)
## 'data.frame':    32 obs. of  5 variables:
##  $ 번호            : Factor w/ 32 levels "1","10","11",..: 1 12 23 27 28 29 30 31 32 2 ...
##  $ 주차장명        : Factor w/ 32 levels "가양라이품","개화산역",..: 22 4 2 14 13 8 29 12 30 5 ...
##  $ 주차면수        : Factor w/ 31 levels "107","1092","1260",..: 18 31 14 26 12 19 8 7 17 22 ...
##  $ 잔여주차가능대수: Factor w/ 32 levels "10","102","1038",..: 19 28 15 27 13 20 10 5 16 22 ...
##  $ datetime        : chr  "2019-08-18 05:05:55 KST" "2019-08-18 05:05:55 KST" "2019-08-18 05:05:55 KST" "2019-08-18 05:05:55 KST" ...

데이터 시각화(Plot)

You can also embed plots, for example:

# 형식 변경 전 사본으로 복사
charting <- useable_df

# as.numeric() 또는 as.integer()로 형변환
charting$`주차면수` <- as.integer(charting$`주차면수`)
charting$`잔여주차가능대수` <- as.integer(charting$`잔여주차가능대수`)

그런 다음 차트를 그려주면,

Column <- gvisColumnChart(charting %>% select(-`번호`))
plot(Column)

주차 면수 즉, capacity가 파란색이고 가능 대수(빈자리)가 빨간색인데 들쭉날쭉한 게 눈에 잘 안 들어옵니다. 차트 종류를 바꿔봅니다.

Area <- gvisAreaChart(charting %>% select(-`번호`))
plot(Area)

훨씬 낫습니다. 그런데 잔여 대수가 주차면수보다 많을 리가 없을 텐데요. y축 단위도 뭔가 이상하면서 익숙합니다. 주차장 개수와 동일하게 데이터 한 세트가 32줄로 이뤄져있는데 공교롭게도 그 언저리 숫자네요.

str(charting)
‘data.frame’:32 obs. of 5 variables:
$ 번호 : Factor w/ 32 levels “1”,“10”,“11”,..: 1 12 23 27 28 29 30 31 32 2 …
$ 주차장명 : Factor w/ 32 levels “가양라이품”,“개화산역”,..: 22 4 2 14 13 8 29 12 30 5 …
$ 주차면수 : num 18 31 14 26 12 19 8 7 17 22 …
$ 잔여주차가능대수: num 14 21 12 23 7 16 8 2 13 18 …

데이터 자체가 문제였습니다. 저 위에 factor일 때와 값이 아예 달라졌네요. 숫자를 정확한 값으로 바꿔줍니다. {factor to integer r - Google Search} 가장 직관적인 솔루션은 문자형으로 먼저 변환 후 숫자로 한번 더 변환하는 것입니다.

# charting 데이터를 다시 불러온 뒤 실행(이미 데이터값에 오류가 생겼으므로)
charting <- useable_df

charting$`주차면수` <- as.numeric(as.character(charting$`주차면수`))
charting$`잔여주차가능대수` <- as.numeric(as.character(charting$`잔여주차가능대수`))
# charting$주차장명 <- as.character(charting$주차장명)

Column <- gvisColumnChart(charting %>% select(`주차장명`, `주차면수`, `잔여주차가능대수`))
plot(Column)
Area <- gvisAreaChart(charting %>% select(`주차장명`, `주차면수`, `잔여주차가능대수`))
plot(Area)

차트로 그려놓으니 뭔가 그럴싸해 보이기도 하고 원하는 시간대 주차현황을 알 수 없으니 별 소득이 없는 것도 같습니다. 여유가 된다면 위 차트를 시간단위로 모두 그려서 애니메이션처럼 만들어도 괜찮겠네요.

하지만 아직 소기의 목적을 달성하지 못했습니다.

Note that the echo = FALSE parameter was added to the code chunk to prevent printing of the R code that generated the plot.