브런치 글 [생활 속 데이터분석] 주차장에 자리 있나요? https://brunch.co.kr/@llun/24의 코드입니다.
브런치 플랫폼상 코드 복사가 안 되고 코드 하이라이트 기능이 없는 한계가 있어 마크다운으로 제공합니다.
library(dplyr)
library(ggplot2)
library(readxl)
library(knitr)
# 데이터 로드
useable_dfs <- data.frame()
for (filepath in dir(path = "~/R/scrapped/", pattern = "[.]xlsx$")) {
scrapped <- read_excel(filepath)
useable_dfs <- bind_rows(useable_dfs, scrapped)
}
# 단순중복 체크
useable_dfs[duplicated(useable_dfs),] %>% nrow()
# 단순중복(동일한 데이터) 제거
useable_dfs <- useable_dfs[!duplicated(useable_dfs),]
str(useable_dfs)
# 작업용 Raw 데이터 사본 생성
# parking <- useable_dfs
## useable_dfs$번호 <- as.character(useable_dfs$번호)
## parking <- bind_rows(parking, useable_dfs)
parking$datetime <- as.POSIXct(format(parking$datetime, tz="Asia/Seoul", usetz=TRUE))
# 분단위 데이터 한정(동일 분(minute) 내의 다른 데이터는 제거)
parking$datetime[1] # 원래 데이터
## [1] "2019-08-04 16:55:11 KST"
substr(parking$datetime[1], 1, 16) # 초 이하 버림
## [1] "2019-08-04 16:55"
# 임시 컬럼 dup 생성
parking$dup <- paste(parking$`주차장명`, as.POSIXct(substr(parking$datetime, 1, 16)))
x <- parking[duplicated(parking$dup),]
# 중복 제거
parking <- parking[!duplicated(parking$dup),] %>% select(-dup)
# 자료형 변환
parking$datetime <- as.POSIXct(parking$datetime) # POSIX로 변환
parking$`주차면수` <- as.numeric(as.character(parking$`주차면수`))
parking$`잔여주차가능대수` <- as.numeric(as.character(parking$`잔여주차가능대수`))
#parking$번호 <- as.factor(parking$번호)
# 시간 추가
parking$hour <- lubridate::hour(parking$datetime)
Chart <- parking %>% group_by(hour) %>% tally(mean(`잔여주차가능대수`))
Chart
## # A tibble: 24 x 2
## hour n
## <int> <dbl>
## 1 0 306.
## 2 1 309.
## 3 2 313.
## 4 3 316.
## 5 4 318.
## 6 5 320.
## 7 6 314.
## 8 7 295.
## 9 8 261.
## 10 9 234.
## # ... with 14 more rows
ggplot(Chart, aes(x = hour, y = n)) +
geom_area()
ggsave("1_area.png", width = 6, height = 4, units = "in", dpi = 200)
ggplot(Chart, aes(x = hour, y = n)) +
geom_line()
# 사용자정의 함수 이용(반복 사용되는 인수를 간편하게 수정하기 위함)
f.ggsave("2_line.png")
# 주차장별로 구분
Chart <- parking %>% group_by(`주차장명`, hour) %>% tally(mean(`잔여주차가능대수`))
ggplot(Chart, aes(x = hour, y = n)) +
geom_line() +
facet_wrap(vars(`주차장명`))
ggsave("3_주차장구분.png", width = 12, height = 8, units = "in", dpi = 100)
# 가로세로 적당한 크기로 펼쳐줍니다.
ggplot(Chart, aes(x = hour, y = n)) +
geom_line() +
facet_wrap(`주차장명` ~ ., ncol = 4)
f.ggsave(filename = "4_주차장facet(4x8).png", target = "facet")
## 스케일이 달라 거의 직선으로 보이는 경우(서울역관광버스주차장)
## 가용 비율로 변경
### -> 더 간단한 해결방법. 단, 플롯마다 y축 텍스트가 추가되어 복잡
ggplot(Chart, aes(x = hour, y = n)) +
geom_line() +
facet_wrap(`주차장명` ~ ., ncol = 4, scales = "free")
f.ggsave("4-1_주차장facet(4x8).png", "facet")
###
# 주차면수 불러오기
x <- parking %>% distinct(`주차장명`, `주차면수`)
# 주차면수 join
Chart <- left_join(Chart, x[1:32,])
## Joining, by = "주차장명"
# 여유 비율을 ratio로 추가
Chart %>% mutate(ratio = n/`주차면수`*100) %>%
ggplot(aes(x = hour, y = ratio)) +
geom_line() +
facet_wrap(`주차장명` ~ ., ncol=4)
f.ggsave("5_주차가용비율.png", "facet")
Chart %>% mutate(ratio = n/`주차면수`*100) %>%
ggplot(aes(x = hour, y = ratio)) +
geom_line() +
scale_x_continuous(breaks = seq(0, 23, 3)) +
facet_wrap(`주차장명` ~ ., ncol=4) +
theme_minimal()
f.ggsave("5-1_테마변경.png", "facet")
# 현재시간대와 동일 시간대의 데이터만 확인
Chart %>% filter(hour == lubridate::hour(Sys.time())) %>%
kable()
| 주차장명 | hour | n | 주차면수 |
|---|---|---|---|
| 가양라이품 | 3 | 34.590389 | 38 |
| 개화산역 | 3 | 261.009153 | 322 |
| 개화역 | 3 | 397.696796 | 483 |
| 구로디지털단지역 | 3 | 53.504577 | 92 |
| 구파발역 | 3 | 345.763158 | 399 |
| 동대문 | 3 | 836.272311 | 1092 |
| 마포유수지 | 3 | 450.770023 | 505 |
| 복정역 | 3 | 309.926774 | 363 |
| 사당노외 | 3 | 89.590389 | 184 |
| 서울역관광버스주차장 | 3 | 35.000000 | 33 |
| 세종로 | 3 | 1142.122426 | 1260 |
| 수락산역 | 3 | 107.732265 | 157 |
| 수서역남 | 3 | 17.700229 | 22 |
| 수서역북 | 3 | 447.846682 | 570 |
| 신대방역 | 3 | 17.058352 | 59 |
| 신방화역 | 3 | 125.591533 | 199 |
| 신설동공영 | 3 | 3.000000 | 79 |
| 신천유수지 | 3 | 174.664760 | 221 |
| 영등포구청역 | 3 | 65.526316 | 137 |
| 용산주차빌딩 | 3 | 388.377574 | 561 |
| 웃우물공영 | 3 | 26.621281 | 39 |
| 잠실역 | 3 | 298.921053 | 357 |
| 장안2동 | 3 | 6.836384 | 39 |
| 적선노외 | 3 | 591.000000 | 600 |
| 종묘 | 3 | 1236.784897 | 1316 |
| 천왕역 | 3 | 230.646453 | 328 |
| 천호역 | 3 | 806.560641 | 1430 |
| 학여울역 | 3 | 120.731121 | 180 |
| 한강진역 | 3 | 137.310069 | 176 |
| 화랑대역 | 3 | 271.304348 | 332 |
| 훈련원공원 | 3 | 1009.986270 | 873 |
| 흑석동공영 | 3 | 77.149886 | 107 |
# 주차장 가용율(ratio) 추가
# Chart <- Chart %>% mutate(ratio = n/주차면수*100) #일반적인 방법
Chart$ratio <- Chart$n/Chart$`주차면수`*100
Chart$label <- ifelse(Chart$hour == lubridate::hour(Sys.time()), paste0(round(Chart$ratio, digits = 2),"%"), NA)
Plot <- ggplot(Chart, aes(x = hour, y = ratio)) +
geom_line() +
geom_text(aes(label = label,
x = lubridate::hour(Sys.time()), y = ratio)) +
geom_vline(xintercept = lubridate::hour(Sys.time()), color = "red", linetype = 2) + # as.numeric() transformation
scale_x_continuous(breaks = seq(0, 23, 3)) +
facet_wrap(`주차장명` ~ ., ncol=4) +
theme_minimal()
ggsave("5-2_수직선라벨추가.png", Plot, width = 12, height = 8, units = "in", dpi = 100)
# current_hour <- 12 # 하드코딩
current_hour <- lubridate::hour(Sys.time()) # 현재시간대 이용
Chart$label <- ifelse(Chart$hour == current_hour, paste0(round(Chart$ratio, digits = 2),"%"), NA)
Plot <- ggplot(Chart, aes(x = hour, y = ratio)) +
geom_line() +
geom_text(aes(label = label, x = current_hour, y = ratio,
vjust = 0, hjust = 0), size = 3) +
geom_vline(xintercept = current_hour, color = "red", linetype = 2) + # as.numeric() transformation
scale_x_continuous(breaks = seq(0, 23, 3)) +
theme(panel.grid.major = element_line(color = "blue", size = 1)) +
facet_wrap(`주차장명` ~ ., ncol=4) +
theme_minimal()
ggsave("6_튜닝(현재시각기준).png", Plot, width = 12, height = 8, units = "in", dpi = 100)
current_hour <- 12 # 다른 시간대 확인을 위해 하드코딩
Chart$label <- ifelse(Chart$hour == current_hour, paste0(round(Chart$ratio, digits = 2),"%"), NA)
Plot <- ggplot(Chart, aes(x = hour, y = ratio)) +
geom_line() +
geom_text(aes(label = label, x = current_hour, y = ratio,
vjust = 0, hjust = 0), size = 3) +
geom_vline(xintercept = current_hour, color = "red", linetype = 2) + # as.numeric() transformation
scale_x_continuous(breaks = seq(0, 23, 3)) +
facet_wrap(`주차장명` ~ ., ncol=4) +
theme_minimal()
ggsave("6-1_시간변경.png", Plot, width = 12, height = 8, units = "in", dpi = 100)
# for loop(반복문)로 전체 시간대 확인
for (current_hour in seq(0,23)) {
Chart$label <- ifelse(Chart$hour == current_hour, paste0(round(Chart$ratio, digits = 2),"%"), NA)
Plot <- ggplot(Chart, aes(x = hour, y = ratio)) +
geom_line() +
geom_text(aes(label = label, x = current_hour, y = ratio,
vjust = 0, hjust = 0), size = 3) +
geom_vline(xintercept = current_hour, color = "red", linetype = 2) +
scale_x_continuous(breaks = seq(0, 23, 3)) +
facet_wrap(`주차장명` ~ ., ncol=4) +
theme_minimal()
ggsave(sprintf("7_%02d시.png", current_hour), Plot, width = 12, height = 8, units = "in", dpi = 100)
}
코드를 작성한 과정에 대해서는 브런치 발행글을 참고해주세요.
To do more, see Interactive Documents.