데이터 출처: SKT Data Hub
Github Code: Jun4871 Github
SK Data Hub에서 가져온 19년 12월 서울시 유동인구 데이터 자료를 분석해보고자 한다. 분석의 목적은 ’유동인구가 가장 발생한 날짜, 지역, 시간대’를 알아보는 것이다. 기지국의 로그정보를 기반으로 유동인구를 파악하는 것이기 때문에 전체 유동인구 자료가 아님을 고려하고 분석해보도록 하겠다.
데이터 전처리 및 시각화 등에 필요한 패키지들을 활성화.
#install.packages("ggthemes")
#install.packages("gridExtra")
library(gridExtra)
library(ggthemes)
library(tidyverse)
library(lubridate)
library(DT)
library(ggplot2)
library(plotly)
library(mlbench)
library(formattable)
데이터를 불러오고 기본적인 데이터 가공 및 파악을 해보자. 구조를 확인해보니 총 7개의 컬럼 (날짜, 측정시간, 나이, 성별, 시, 군구, 유동인구) 으로 이루어져 있다. 컬럼 명을 영문으로 바꿔주고 날짜형식을 보기편하게 바꿔주었다.
time : int 형식, 0시부터 23시까지 총 24개의 값을 가지고 있다.
age : int 형식, 20대부터 70대까지 6개의 값을 가지고 있다.
sex : factor 형식, 남성과 여성으로 레벨이 구분되어 있고, 데이터 개수가 각 111,600으로 동일함을 알 수 있다.
town : factor 형식, 총 25개의 지역으로 레벨이 구분되어 있고, 각 구별로 8928개의 데이터 셋을 가지고 있음을 알 수 있다.
population : int 형식, 측정값의 최소치는 4,570이고 최대치는 124,450 그리고 평균은 27,484로 대략적인 수치를 파악할 수 있다.
#rm(list=ls())
population <- read.csv("Population_1912.csv")
# R에서 넘어온 코드
# filename <- paste0("Population_",month,".csv")
# population <- read.csv(filename)
# 컬럼명 영문화
colnames(population) <- c("Date", "Time","Age", "Sex", "City", "Town","Population")
# city 컬럼 삭제
population <- population[,-5]
# 데이터 구조 파악
str(population)
## 'data.frame': 223200 obs. of 6 variables:
## $ Date : int 20191201 20191201 20191201 20191201 20191201 20191201 20191201 20191201 20191201 20191201 ...
## $ Time : int 0 0 0 0 1 1 1 1 1 1 ...
## $ Age : int 20 30 40 70 20 40 50 50 50 70 ...
## $ Sex : Factor w/ 2 levels "남성","여성": 2 1 2 2 2 1 1 1 1 2 ...
## $ Town : Factor w/ 25 levels "강남구","강동구",..: 25 21 16 20 23 13 6 14 23 8 ...
## $ Population: int 26490 23710 23030 17690 15400 30750 27440 22410 13740 10720 ...
summary(population)
## Date Time Age Sex Town
## Min. :20191201 Min. : 0.00 Min. :20 남성:111600 강남구 : 8928
## 1st Qu.:20191208 1st Qu.: 5.75 1st Qu.:30 여성:111600 강동구 : 8928
## Median :20191216 Median :11.50 Median :45 강북구 : 8928
## Mean :20191216 Mean :11.50 Mean :45 강서구 : 8928
## 3rd Qu.:20191224 3rd Qu.:17.25 3rd Qu.:60 관악구 : 8928
## Max. :20191231 Max. :23.00 Max. :70 광진구 : 8928
## (Other):169632
## Population
## Min. : 4570
## 1st Qu.: 18390
## Median : 25520
## Mean : 27484
## 3rd Qu.: 33920
## Max. :124450
##
# age 컬럼 레벨구분
population$Age <- factor(population$Age, levels = c("20","30","40","50","60","70"))
# NA 여부파악
sum(is.na(population))
## [1] 0
# 날짜형식으로 변경
population$Date <- ymd(population$Date)
# 일별, 시간대별 유동인구수
date_time_grouping <- population %>%
group_by(Date, Time) %>%
summarize(Populaion_Ratio = sum(Population), Date_Time_mean = mean(Population)) %>%
arrange(desc(Populaion_Ratio,Date_Time_mean)) %>%
as.data.frame()
# 일별 유동인구수의 합과 평균
date_grouping <- population %>%
group_by(Date) %>%
summarize(Date_Total_sum = sum(Population), Date_Total_mean = mean(Population)) %>%
as.data.frame() %>%
arrange(desc(Date_Total_sum))
# 시간대 별 유동인구수
time_grouping <- population %>%
group_by(Time) %>%
summarize(Population_Ratio = sum(Population), Time_Total_mean = mean(Population)) %>%
as.data.frame() %>%
arrange(desc(Population_Ratio))
# 지역구 유동인구수
town_grouping <- population %>%
group_by(Town) %>%
summarize(Population_Ratio = sum(Population)) %>%
arrange(desc(Population_Ratio)) %>%
as.data.frame()
# comma(town_grouping[1,2], 0)
19년 12월 전체 데이터 중 가장 높은 유동인구수를 보인 시점은 2019-12-02 : 14 시이며, 총 8,733,140 명의 수치로 가장 높았다.
오전 -> 오후 시간대로 진입할수록 유동인구의 수가 늘어나고 있음을 알 수 있었으며, 가장 많은 수치를 보인 시간대는 16시로 263,753,780 명이다.
19년 12월 서울시 내 유동인구가 가장 많은 날은 2019-12-02 이며, 201,496,500 명이다.
1위 : 강남구 447,555,710 명, 2위 : 송파구 388,063,340, 3위 : 강서구 325,447,120
날짜별로 유동인구의 분포를 파악해보자. 먼저 plot 함수를 사용해보니, 규칙성이 보인다. 유동인구수가 5개 묶음으로 솟아져있는 것을 확인할 수 있는데 이 구간은 전부 평일이다. 회사, 학교, 은행 등 대부분의 기관들의 운영시간 역시 평일이므로 유동인구가 많음을 알 수 있다. 반면에 주말은 수치가 급감했는데, 업무적 의무성이 사라지니 특별한 이유없이 외출할 일은 없었을 것이다. 주말이 아님에도 수치가 급감한 부분이 있어 확인해보니, 이 날은 크리스마스 날 이었고, 30일, 31일은 평일임에도 다소 낮은 유동인구수치를 보였는데, 1월 1일이 휴일이라 연이어 쉬는 회사들도 있었기 때문인 것 같다.
# 일별 유동인구수 그래프
#plot(date_time_grouping$date, date_time_grouping$date_time_sum, xlab = "Date", ylab = "Population", main= "일별 유동인구수")
ggplot(date_time_grouping, aes(x=Date, y=Populaion_Ratio)) +
geom_point(size=5,alpha=0.5) +
theme_calc() +
theme(axis.text.x = element_text(size=20)) +
theme(axis.text.y = element_text(size=20)) +
ggtitle("19년 12월 유동인구수") +
theme(plot.title = element_text(face="bold", hjust=0.5, vjust=1, size=25, color="#008B8B")) +
xlab("날짜") +
ylab("유동인구") +
theme(axis.title.x=element_text(family="NanumGothic",
face="bold",
hjust=0.5,
size=20,
color="Black",
angle=0),
axis.title.y=element_text(family="NanumGothic",
face="bold",
vjust=0.5,
size=20,
color="Black",
angle=0)) +
scale_y_continuous(limits=c(min(date_time_grouping$Populaion_Ratio),
max(date_time_grouping$Populaion_Ratio)),
labels=scales::comma)
시간대별 유동인구수를 기준으로 시각화를 해보았다. 0시부터 지속적으로 유동인구가 줄기 시작하다가 6시부터 다시 유동인구수가 늘어나는 것을 알 수 있다. 이것 역시 일반적인 사람들의 생활패턴을 반영한다고 볼 수 있다. 등교준비, 출근준비 등으로 인해 6시를 기점으로 그래프가 상승하는 것으로 보이고, 17시 이후에는 일반적으로 일과가 어느정도 마무리 되는 시점으로 볼 수 있고 그래프가 하락한다.
# 시간대 별 유동인구수 그래프
# plot(time_grouping$time, time_grouping$time_total_sum, xlab = "Time", ylab = "Population", main= "시간별 유동인구수")
ggplot(time_grouping, aes(x=time_grouping$Time, y=time_grouping$Population_Ratio)) +
# geom_line(size=2,alpha=0.9) +
geom_point(size=5,alpha=0.9, shape=22,color = 'red',
fill = 'gray30', stroke = 2) +
theme_calc() +
# coord_fixed() +
theme(axis.text.x = element_text(size=20)) +
theme(axis.text.y = element_text(size=20)) +
ggtitle("19년 12월 시간대 별 유동인구수") +
theme(plot.title = element_text(face="bold", hjust=0.5, vjust=1, size=25, color="#008B8B")) +
xlab("시간") +
ylab("유동인구") +
theme(axis.title.x=element_text(family="NanumGothic",
face="bold",
hjust=0.5,
size=20,
color="Black",
angle=0),
axis.title.y=element_text(family="NanumGothic",
face="bold",
vjust=0.5,
size=20,
color="Black",
angle=0)) +
scale_y_continuous(limits=c(min(time_grouping$Population_Ratio),
max(time_grouping$Population_Ratio)),
labels=scales::comma) +
scale_x_continuous(breaks=c(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24))
# coord_cartesian(ylim=c(0,max(time_grouping$time_total_sum)))
# scale_y_continuous(limits = c(min(time_grouping$time_total_sum), max(time_grouping$time_total_sum)))
# coord_cartesian(ylim = c(0, max(time_grouping$time_total_sum)))
# coord_cartesian(ylim=c(100, 200))
지역별 유동인구수를 시각화를 해보았다. 19년 12월 한 달 기준 유동인구가 가장 많았던 지역으로는 1위가 강남구, 2위가 송파구, 3위가 강서구가 되겠다. 강남구 (447555710)와 송파구(388063340)의 수치가 타지역보다 월등히 높은데, 두 지역을 보면 상권규모가 상당히 큰 지역이라는 특징이 있다. 이 두 지역에서 소위 ’맛집’으로 소문난 가게들과 접대하기에 적합한 고급 레스토랑들이 거리에 즐비하고 있다는 것은 자명한 사실이다. 이 밖에도 쇼핑센터와 각 종 편의시설이 몰려있는 지역이니 만인에게 사랑받는 장소가 아닐 수 없다는 생각이 든다.
# 지역별 유동인구수
#plot(town_grouping, town_grouping$town_sum, xlab = "Town", ylab = "Population", main= "지역별 유동인구수")
ggplot(town_grouping, aes(x=town_grouping$Town, y=town_grouping$Population_Ratio)) +
geom_point(size=8,alpha=0.9, shape=22,color = 'red',
fill = 'gray30', stroke = 2) +
theme_calc() +
ggtitle("19년 12월 지역별 유동인구수") +
theme(plot.title = element_text(face="bold", hjust=0.5, vjust=1, size=30, color="#008B8B")) +
xlab("지역") +
ylab("유동인구") +
theme(axis.title.x=element_text(family="NanumGothic",
face="bold",
hjust=0.5,
size=25,
color="Black",
angle=0),
axis.title.y=element_text(family="NanumGothic",
face="bold",
vjust=0.5,
size=25,
color="Black",
angle=0)) +
scale_y_continuous(limits=c(min(town_grouping$Population_Ratio),
max(town_grouping$Population_Ratio)),
labels=scales::comma) +
theme(axis.text.x = element_text(size=13, face ="bold")) +
theme(axis.text.y = element_text(size=20))
# scale_x_continuous(breaks=c(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24))
# coord_cartesian(ylim=c(0,max(time_grouping$time_total_sum)))
# ggplot(town_grouping, aes(x = reorder(Town , Population_Ratio), y = Population_Ratio, fill = Population_Ratio)) +
# geom_bar(stat = "identity") +
# xlab("구") +
# ylab("유동인구 총합") +
# coord_flip() +
# theme_bw()