주차장에 자리 있나요? (2 of 3)

실시간을 넘어서 미래의 상태를 알고 싶을 때

브런치 글 [생활 속 데이터분석] 주차장에 자리 있나요? 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.