서울시 거주자 인구이동 및 소비현황 시각화
분석 개요
- 목적: 서울시 거주자의 인구이동 및 소비현황 시각화를 하고자 함
분석 데이터
- 코리아크레딧뷰로(주)의 인구전입데이터
- 코리아크레딧뷰로(주)의 인구전출데이터
- 국토교통부의 시군구행정코드 및 경계지도 데이터(공공데이터)
분석 과정
1. R 패키지 로드 및 옵션 설정
R패키지 로드
options(scipen = 999) # full number
#load packages
library(data.table)
library(dplyr)
library(ggplot2)
#map 관련 라이브러리
library(ggmap) # 필요시 yum install libjpeg-devel
library(raster)
library(rgeos) # 필요시 yum install geos geos-devel
library(maptools)
library(rgdal) # 필요시 yum install gdal gdal-devel proj proj-devel
library(sp)
library(geosphere)
library(tibble)
#network 관련 라이브러리
library(igraph)
library(ggraph)
library(visNetwork)
knitr::opts_chunk$set(warning = FALSE, message=FALSE)
ggplot 관련 테마설정
my_theme <-
theme(
panel.background = element_blank(),
axis.title = element_blank(),
axis.text = element_blank(),
axis.ticks = element_blank(),
plot.title = element_text(hjust = 0.5, face = 'bold'),
legend.text = element_text(family = 'NanumGothic',
size = 8, face = 'bold'),
legend.title = element_text(family = 'NanumGothic',
size = 10, face = 'bold')
)
my_theme_bar <- theme(panel.background = element_blank(),
plot.title = element_text(hjust = 0.5, face = 'bold'),
axis.text.x = element_text(angle = 60, hjust = 1))
데이터 로드
data_path <- "/home/joohj7/analysis/project/2020_DT_교통예측시연"
# list.files(data_path, pattern = "csv")
MOVE_TYP1 <- fread(file.path(data_path, "TB_COL_KC_T023_MOVE_TYP1.csv"))
MOVE_TYP2 <- fread(file.path(data_path, "TB_COL_KC_T023_MOVE_TYP2.csv"))
시군구행정지도와 시군구코드 매핑
#시군구 데이터 매핑
siggfunc <- function(folder, layername) {
sigg_import <-
readOGR(
dsn = folder,
layer = layername,
encoding = 'CP949')
#좌표계 변환
to_crs = CRS("+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs")
sigg <- spTransform(sigg_import, to_crs)
siggDF <- fortify(model = sigg)
sigg@data$id <- rownames(x=sigg@data)
# 이제 두 데이터프레임을 병합
siggDF <- merge(x= siggDF,
y=sigg@data[, c("id", 'SIG_KOR_NM',
"SIG_ENG_NM", "SIG_CD")],
by='id', all.x= TRUE)
# order를 10으로 나누었을 때 나머지가 1인 행만 남김(조밀도를 줄임)
siggDF <- siggDF[siggDF$order %% 10 == 1, ]
# 부속지역을 제외(조밀도를 줄임)
siggDF <- subset(x = siggDF, subset = siggDF$piece == 1)
# id와 order 기준으로 오름차순 정렬
siggDF <- siggDF[order(siggDF$id, siggDF$order), ]
return (siggDF)
}
sigg_df<- siggfunc(folder = '/home/joohj7/analysis/project/2020_DT_교통예측시연/SIG_201905',
layername = 'TL_SCCO_SIG')
## OGR data source with driver: ESRI Shapefile
## Source: "/home/joohj7/analysis/project/2020_DT_교통예측시연/SIG_201905", layer: "TL_SCCO_SIG"
## with 250 features
## It has 3 fields
head(sigg_df, 3)
id | long | lat | order | hole | piece | group | SIG_KOR_NM | SIG_ENG_NM | ||
---|---|---|---|---|---|---|---|---|---|---|
1 | 0 | 127.0086 | 37.58047 | 1 | FALSE | 1 | 0.1 | 종로구 | Jongno-gu | |
11 | 0 | 127.0100 | 37.58028 | 11 | FALSE | 1 | 0.1 | 종로구 | Jongno-gu | |
21 | 0 | 127.0117 | 37.58151 | 21 | FALSE | 1 | 0.1 | 종로구 | Jongno-gu |
3 rows | 1-10 of 11 columns
2. 데이터 전처리
서울시 데이터 필터링
#지도에서 서울시만 추출
seoulDF<- sigg_df[substr(sigg_df$SIG_CD,1,2)==11,] #서울특별시:11
#지역이름의 유일이름 추출
area_df<- unique(sigg_df[, c("SIG_CD", "SIG_KOR_NM")])
head(area_df, 3)
SIG_CD | SIG_KOR_NM | |
---|---|---|
1 | 11110 | 종로구 |
2333 | 11140 | 중구 |
4251 | 11350 | 노원구 |
3 rows
#서울에서 서울로 옮긴경우
#전입데이터
SEOUL_MOVE_TYP1 <- MOVE_TYP1[MOVE_TYP1$PRV_CTNCD<=11740 &
MOVE_TYP1$CUR_CTNCD<=11740]
SEOUL_MOVE_TYP1 <- as.data.table(SEOUL_MOVE_TYP1)
head(SEOUL_MOVE_TYP1, 3)
IRIS_KEY | IRIS_PARTITION <S3: integer64> | GB | BS_YR_MON | PRV_PVNCD | PRV_CTNCD | CUR_CTNCD | CUR_ADMCD | GENDER | AGE_BIN | |
---|---|---|---|---|---|---|---|---|---|---|
1 | 20191001000000 | 1 | 201910 | 11 | 11740 | 11215 | 11215860 | 1 | 60 | |
1 | 20191001000000 | 1 | 201910 | 11 | 11530 | 11500 | 11500530 | 1 | 20 | |
1 | 20191001000000 | 1 | 201910 | 11 | 11215 | 11260 | 11260520 | 1 | 30 |
3 rows | 1-10 of 17 columns
#전출데이터
MOVE_TYP2 <- MOVE_TYP2[IRIS_KEY==2017] #필터링
SEOUL_MOVE_TYP2 <- MOVE_TYP2[MOVE_TYP2$CUR_CTNCD<=11740 &
MOVE_TYP2$AFT_CTNCD<=11740]
SEOUL_MOVE_TYP2 <- as.data.table(SEOUL_MOVE_TYP2)
head(SEOUL_MOVE_TYP2, 3)
IRIS_KEY | IRIS_PARTITION <S3: integer64> | GB | BS_YR_MON | CUR_BS_YR_MON | CUR_CTNCD | CUR_ADMCD | AFT_PVNCD | AFT_CTNCD | |
---|---|---|---|---|---|---|---|---|---|
2017 | 20191001000000 | 2 | 201910 | 201710 | 11680 | 11680690 | 11 | 11650 | |
2017 | 20191001000000 | 2 | 201910 | 201710 | 11320 | 11320514 | 11 | 11170 | |
2017 | 20191001000000 | 2 | 201910 | 201710 | 11290 | 11290555 | 11 | 11650 |
3 rows | 1-9 of 18 columns
전입/전출 집계데이터 산출
#전입 집계
#지역구내 집계 통일
SEOUL_SUMM_TYP1 <- SEOUL_MOVE_TYP1 %>%
group_by(PRV_CTNCD, CUR_CTNCD, AGE_BIN) %>%
summarise_at(c("AVG_MON_INCOME", "MED_MON_INCOME","AVG_MON_CARDSPND"),
mean, na.rm=TRUE)
head(SEOUL_SUMM_TYP1, 3)
PRV_CTNCD | CUR_CTNCD | AGE_BIN | AVG_MON_INCOME | MED_MON_INCOME | AVG_MON_CARDSPND |
---|---|---|---|---|---|
11110 | 11110 | 20 | 1913.794 | 1796.235 | 860.4706 |
11110 | 11110 | 30 | 3213.735 | 2578.794 | 1429.9412 |
11110 | 11110 | 40 | 3579.118 | 3047.676 | 1782.8235 |
3 rows
#전출 집계
#지역구내 집계 통일
SEOUL_SUMM_TYP2 <- SEOUL_MOVE_TYP2 %>%
group_by(CUR_CTNCD, AFT_CTNCD, AGE_BIN) %>%
summarise_at(c("AVG_MON_INCOME", "MED_MON_INCOME","AVG_MON_CARDSPND"),
mean, na.rm=TRUE)
head(SEOUL_SUMM_TYP2, 3)
CUR_CTNCD | AFT_CTNCD | AGE_BIN | AVG_MON_INCOME | MED_MON_INCOME | AVG_MON_CARDSPND |
---|---|---|---|---|---|
11110 | 11110 | 20 | 1574.882 | 1502.471 | 707.7353 |
11110 | 11110 | 30 | 2587.676 | 2172.265 | 1323.1176 |
11110 | 11110 | 40 | 3142.941 | 2623.294 | 1642.7353 |
3 rows
전출지역 이름 매핑
#area center name point
center <- seoulDF %>% group_by(SIG_CD, SIG_KOR_NM) %>%
summarise_at(c("long", "lat"), function(x)(min(x)+(max(x)-min(x))/2))
center <- as.data.table(center)
#시군구 center label위치 세부조정 작업
center[SIG_KOR_NM=="서대문구"]$lat <- center[SIG_KOR_NM=="서대문구"]$lat -0.01
center[SIG_KOR_NM=="마포구"]$lat <- center[SIG_KOR_NM=="마포구"]$lat -0.005
center[SIG_KOR_NM=="종로구"]$lat <- center[SIG_KOR_NM=="종로구"]$lat -0.02
center[SIG_KOR_NM=="양천구"]$lat <- center[SIG_KOR_NM=="양천구"]$lat -0.01
center[SIG_KOR_NM=="강남구"]$lat <- center[SIG_KOR_NM=="강남구"]$lat -0.01
center[SIG_KOR_NM=="동대문구"]$lat <- center[SIG_KOR_NM=="동대문구"]$lat -0.005
center[SIG_KOR_NM=="동작구"]$lat <- center[SIG_KOR_NM=="동작구"]$lat +0.005
center[SIG_KOR_NM=="동작구"]$long <- center[SIG_KOR_NM=="동작구"]$long +0.005
center[SIG_KOR_NM=="서초구"]$long <- center[SIG_KOR_NM=="서초구"]$long -0.01
center[SIG_KOR_NM=="강북구"]$lat <- center[SIG_KOR_NM=="강북구"]$lat -0.01
center[SIG_KOR_NM=="성북구"]$lat <- center[SIG_KOR_NM=="성북구"]$lat -0.005
center[SIG_KOR_NM=="구로구"]$lat <- center[SIG_KOR_NM=="구로구"]$lat +0.001
#지역구 전출집계인구수
SEOUL_count <- SEOUL_MOVE_TYP2 %>% group_by(CUR_CTNCD, AFT_CTNCD) %>%
summarise_at("POP_CNT", sum, na.rm=TRUE)
head(SEOUL_count, 3)
CUR_CTNCD | AFT_CTNCD | POP_CNT |
---|---|---|
11110 | 11110 | 118628 |
11110 | 11140 | 467 |
11110 | 11170 | 498 |
3 rows
SEOUL_count <- merge(SEOUL_count, center,
by.x="CUR_CTNCD", by.y="SIG_CD", all.x=T)
SEOUL_count <- merge(SEOUL_count, center,
by.x="AFT_CTNCD", by.y="SIG_CD", all.x=T,
suffixes= c( ".CUR", ".AFT"))
SEOUL_count <- SEOUL_count[order(SEOUL_count$CUR_CTNCD, SEOUL_count$AFT_CTNCD), ]
# 그룹 id 계산하기
unique_mat<- unique(SEOUL_count[,c("CUR_CTNCD", "AFT_CTNCD")])
unique_mat$id <- rownames(unique_mat)
# id 매핑
SEOUL_count <- merge(SEOUL_count, unique_mat,
by=c("AFT_CTNCD", "CUR_CTNCD"))
SEOUL_count <- as.data.table(SEOUL_count)
3. 분석데이터 시각화
3.1. 서울시 인구전출 데이터 분석
지역구 전출 빈도수 (구역내&타지역포함)
# 지역구 전출 빈도수
MOVE_COUNT<- SEOUL_count%>% group_by(SIG_KOR_NM.CUR) %>%
summarise(count = sum(POP_CNT))%>%
arrange(desc(count))
head(MOVE_COUNT, 3)
SIG_KOR_NM.CUR | count |
---|---|
송파구 | 479132 |
강남구 | 435717 |
강서구 | 421715 |
3 rows
# 지역구 전출 코드 매핑
MOVE_COUNT_map <- merge(seoulDF, MOVE_COUNT,
by.x="SIG_KOR_NM", by.y='SIG_KOR_NM.CUR')
MOVE_COUNT_map <- MOVE_COUNT_map[order(MOVE_COUNT_map$id, MOVE_COUNT_map$order),]
MOVE_COUNT_map <- as.data.table(MOVE_COUNT_map)
head(MOVE_COUNT_map, 3)
SIG_KOR_NM | id | long | lat | order | hole | piece | group | SIG_ENG_NM | SIG_CD | |
---|---|---|---|---|---|---|---|---|---|---|
종로구 | 0 | 127.0086 | 37.58047 | 1 | FALSE | 1 | 0.1 | Jongno-gu | 11110 | |
종로구 | 0 | 127.0100 | 37.58028 | 11 | FALSE | 1 | 0.1 | Jongno-gu | 11110 | |
종로구 | 0 | 127.0117 | 37.58151 | 21 | FALSE | 1 | 0.1 | Jongno-gu | 11110 |
3 rows | 1-10 of 11 columns
전체 전출 빈도수(barplot)
# 서울시 지역구 인구 전출 빈도수
ggplot(data = MOVE_COUNT, aes(x=reorder(SIG_KOR_NM.CUR, -count), y=count)) +
geom_bar(stat="identity",fill="purple", alpha=0.5)+ labs(x="지역", y="빈도수")+
scale_y_continuous(limits = c(0, 600000),
breaks = seq(0, 600000, by = 200000))+
my_theme_bar + ggtitle("서울시 지역구 인구 전출 빈도수")
#전체 전출을 빈번하게 하는 지도
ggplot(data = MOVE_COUNT_map,
mapping = aes(x = long, y = lat)) +
geom_polygon(aes(group= group, fill= count),color = 'black') +
geom_text(data= center, aes(x=long, y=lat, label=SIG_KOR_NM), size=3)+
scale_fill_gradient(low = 'white', high = 'red') +
coord_fixed() + my_theme + ggtitle("서울시 지역구 인구 전출 빈도수")
지역구 전출 빈도수
#전체 전출을 빈번하게 하는 지도
MOVE_COUNT2<- SEOUL_count%>% group_by(SIG_KOR_NM.CUR) %>%
filter(SIG_KOR_NM.CUR!=SIG_KOR_NM.AFT)%>% summarise(count = sum(POP_CNT)) %>%
arrange(desc(count))
MOVE_COUNT_map2 <- merge(seoulDF, MOVE_COUNT2,
by.x="SIG_KOR_NM", by.y='SIG_KOR_NM.CUR')
MOVE_COUNT_map2 <- MOVE_COUNT_map2[order(MOVE_COUNT_map2$id, MOVE_COUNT_map2$order),]
MOVE_COUNT_map2 <- as.data.table(MOVE_COUNT_map2)
#서울내 타지역으로의 빈도수(barplot)
ggplot(data = MOVE_COUNT2, aes(x=reorder(SIG_KOR_NM.CUR, -count), y=count)) +
geom_bar(stat="identity",fill="purple", alpha=0.5)+ labs(x="지역", y="빈도수")+
scale_y_continuous(limits = c(0, 60000),
breaks = seq(0, 60000, by = 20000))+
my_theme_bar + ggtitle("서울시 지역구 전출 빈도수")
ggplot(data = MOVE_COUNT_map2,
mapping = aes(x = long, y = lat)) +
geom_polygon(aes(group= group, fill= count),color = 'black') +
geom_text(data= center, aes(x=long, y=lat, label=SIG_KOR_NM), size=3)+
scale_fill_gradient(low = 'white', high = 'red') +
coord_fixed() + my_theme + ggtitle("서울시 지역구 전출 빈도수")
-
전입 전출 데이터는 2년기준.
-
한강 이남간의 전출이 활발한편
-
첫째로 자기 지역(구)에서 전출하여 자기 지역(구)로 전입하는경우가 항상 첫번째.(10만 단위 -> 만 단위로)
-
서울내 전출 자체는 송파구>강남구>강서구>관악구>노원구 순으로 나오나
-
서울내 타지역으로의 전출만을 집계하면 강남구>관악구>서초구>마포구>영등포구 순
-
전체 전출에 비해 송파구, 강서구, 노원구의 경우 타 지역으로의 전출이 많지 않은편
-
종로구,중구, 금천구의 경우 전출인구가 많지 않은 지역
3.2. 서울거주자 인구 전출의 이동량 상위 5지역
#인구 전출 이동량이 높은 지역 산출
MOVE_COUNT2_detail <- SEOUL_count%>%
group_by(SIG_KOR_NM.CUR, SIG_KOR_NM.AFT) %>%
filter(SIG_KOR_NM.CUR!=SIG_KOR_NM.AFT)%>%
summarise(count = sum(POP_CNT)) %>%
arrange(desc(count))
MOVE_COUNT2_detail
SIG_KOR_NM.CUR | SIG_KOR_NM.AFT | count |
---|---|---|
강남구 | 송파구 | 11318 |
양천구 | 강서구 | 10006 |
강남구 | 서초구 | 9497 |
서초구 | 강남구 | 8687 |
강서구 | 양천구 | 8321 |
강동구 | 송파구 | 8182 |
송파구 | 강동구 | 7508 |
서대문구 | 은평구 | 7156 |
서초구 | 동작구 | 6760 |
관악구 | 동작구 | 6607 |
Next
123456
...
60
Previous
1-10 of 597 rows
둘째로 자기 지역(구)에서 타 지역(구)로 전출하는 경우의 순서는 1_강남구->송파구, 2_양천구->강서구, 3_강남구->서초구, 4_서초구->강남구, 5_강서구->양천구 순
서울시 내 지역구별 전출인구의 지도 매핑작업
SEO.MAP_AFT <- merge(seoulDF, SEOUL_count, by.x="SIG_CD", by.y='AFT_CTNCD')
SEO.MAP_AFT <- SEO.MAP_AFT[order(SEO.MAP_AFT$id.x, SEO.MAP_AFT$order),]
SEO.MAP_AFT <- as.data.table(SEO.MAP_AFT)
#서울시 내 지역구별 전출인구의 시각화 함수
area.out.plot<- function(area){
plt<- ggplot(data = SEO.MAP_AFT,
mapping = aes(x = long, y = lat)) +
geom_polygon(aes(group= group), fill= "white",color = 'black') +
geom_polygon(data = SEO.MAP_AFT[SIG_KOR_NM.CUR==area&SIG_KOR_NM.AFT==area],
aes(group= group), fill= "gray",color = 'black')+
geom_polygon(data = SEO.MAP_AFT[SIG_KOR_NM.CUR==area &SIG_KOR_NM.AFT!=area],
aes(group= group, fill= POP_CNT),color = 'black') +
geom_text(data= center, aes(x=long, y=lat, label=SIG_KOR_NM), size=3)+
geom_segment(data = SEOUL_count[SIG_KOR_NM.CUR==area&SIG_KOR_NM.AFT!=area] %>%
group_by(AFT_CTNCD) %>%
arrange(desc(POP_CNT))%>% head(5),
aes(x = long.CUR, y = lat.CUR,
xend = long.AFT, yend = lat.AFT),
color = "darkgreen", size = 0.5,
alpha = 0.8, lineend = "round",
arrow = arrow(length = unit(0.02, "npc")))+
scale_fill_gradient(low = 'white', high = 'red') +
coord_fixed() + my_theme
return(plt)
}
지역구별 전출 상위 5지역 지도시각화
# 강남구 인구 전출 지도
area.out.plot("강남구")
# 양천구 인구 전출 지도
area.out.plot("양천구")
# 서초구 인구 전출 지도
area.out.plot("서초구")
# 강서구 인구 전출 지도
area.out.plot("강서구")
# 송파구 인구 전출 지도
area.out.plot("송파구")
3.3. 전출 네트워크 분석
MOVE_COUNT2_detail$count <- ifelse(MOVE_COUNT2_detail$count/100<10,
NA, MOVE_COUNT2_detail$count)
MOVE_COUNT2_detail<- na.omit(MOVE_COUNT2_detail)
SIG_KOR_NM.CUR <- SEOUL_count %>%
distinct(SIG_KOR_NM.CUR) %>%
rename(label = SIG_KOR_NM.CUR)
SIG_KOR_NM.AFT <- SEOUL_count %>%
distinct(SIG_KOR_NM.AFT) %>%
rename(label = SIG_KOR_NM.AFT)
# 노드 생성 작업
nodes <- full_join(SIG_KOR_NM.CUR, SIG_KOR_NM.AFT, by = "label")
nodes <- nodes %>% rowid_to_column("id")
nodes$shape <- "circle"
# 엣지 생성 작업
edges <- MOVE_COUNT2_detail %>%
left_join(nodes, by = c("SIG_KOR_NM.CUR" = "label")) %>%
rename(from = id)
edges <- edges %>%
left_join(nodes, by = c("SIG_KOR_NM.AFT" = "label")) %>%
rename(to = id)
edges <- edges[, c("from", "to", "count")]
edges <- mutate(edges, width = round(count/10000,1)*10)
서울시 지역구 전입/전출 연관 네트워크
visNetwork(nodes, edges) %>%
visIgraphLayout(layout = "layout_with_fr") %>%
visEdges(arrows = "middle")
- 강남,송파,서초 /노원,성북,강북,중랑/광진,동대문,성동/관악,동작,마포, 영등포/ 서대문,은평,종로 등의 5가지 집단내에서 주로 이동.
- 일부지역구 (중구)는 전출이 활발한 편은 아님
3.4. 서울시 연령별 지역구 전출
#지역으로 전출
AGE_MOVE <- SEOUL_MOVE_TYP2%>% group_by(AFT_CTNCD, AGE_BIN) %>%
summarise(count = sum(POP_CNT))
AGE_MOVE <- merge(AGE_MOVE, area_df, by.x="AFT_CTNCD", by.y="SIG_CD",
all=T)
AGE_MOVE <- as.data.table(AGE_MOVE)
AGE_MOVE <- AGE_MOVE[substr(AFT_CTNCD,1,2)==11, ]
AGE_MOVE%>% group_by(AGE_BIN, AFT_CTNCD) %>%
arrange(AGE_BIN, desc(count))
AFT_CTNCD | AGE_BIN | count | SIG_KOR_NM |
---|---|---|---|
11710 | 20 | 93974 | 송파구 |
11620 | 20 | 91364 | 관악구 |
11500 | 20 | 83038 | 강서구 |
11680 | 20 | 82750 | 강남구 |
11290 | 20 | 77560 | 성북구 |
11350 | 20 | 77081 | 노원구 |
11230 | 20 | 68836 | 동대문구 |
11590 | 20 | 65388 | 동작구 |
11470 | 20 | 63370 | 양천구 |
11380 | 20 | 62790 | 은평구 |
Next
123456
...
15
Previous
1-10 of 150 rows
# 서울시 지역구 전출인구 데이터 집계
AGE_MOVE2 <- SEOUL_MOVE_TYP2%>% group_by(CUR_CTNCD, AFT_CTNCD, AGE_BIN) %>%
filter(CUR_CTNCD!=AFT_CTNCD)%>%
summarise(count = sum(POP_CNT))
AGE_MOVE2 <- merge(AGE_MOVE2, area_df, by.x="AFT_CTNCD", by.y="SIG_CD",
all=T)
AGE_MOVE2 <- merge(AGE_MOVE2, area_df, by.x="CUR_CTNCD", by.y="SIG_CD",
all=T, suffixes = c(".AFT", ".CUR"))
AGE_MOVE2 <- as.data.table(AGE_MOVE2)
AGE_MOVE2 <- AGE_MOVE2[substr(AGE_MOVE2$CUR_CTNCD,1,2)==11&
substr(AGE_MOVE2$AFT_CTNCD,1,2)==11, ]
AGE_MOVE2 <- AGE_MOVE2%>% group_by(AGE_BIN, AFT_CTNCD) %>%
arrange(AGE_BIN, desc(count))
AGE_MOVE2 <- as.data.table(AGE_MOVE2)
- 연령별 지역구 전출 네트워크 전처리
- 전출 1000이상의 데이터만 집계
- 관계를 명확히 보기위해 데이터에 가중치를 줌
연령별 지역구 네트워크
##### 연령별 지역구 네트워크 함수
age_net <- function(age){
AGE_NM.CUR <- AGE_MOVE2[,c("SIG_KOR_NM.CUR")] %>%
distinct(SIG_KOR_NM.CUR) %>%
rename(label = SIG_KOR_NM.CUR)
AGE_NM.AFT <- AGE_MOVE2[,c("SIG_KOR_NM.AFT")] %>%
distinct(SIG_KOR_NM.AFT) %>%
rename(label = SIG_KOR_NM.AFT)
AGE_nodes <- full_join(SIG_KOR_NM.CUR, SIG_KOR_NM.AFT, by = "label")
AGE_nodes <- AGE_nodes %>% rowid_to_column("id")
AGE_nodes$shape <- "circle"
AGE_edges <- AGE_MOVE2[AGE_BIN==age] %>%
filter(count>1000)%>%
left_join(AGE_nodes, by = c("SIG_KOR_NM.CUR" = "label")) %>%
rename(from = id)
AGE_edges <- AGE_edges %>%
left_join(AGE_nodes, by = c("SIG_KOR_NM.AFT" = "label")) %>%
rename(to = id)
AGE_edges <- AGE_edges[, c("from", "to", "count")]
AGE_edges <- mutate(AGE_edges, width = round(count/1000)*5)
vis <- visNetwork(AGE_nodes, AGE_edges) %>%
visIgraphLayout(layout = "layout_with_fr") %>%
visEdges(arrows = "middle")
return(vis)
}
# 20대 인구 전출 네트워크
age_net(20)
# 30대 인구 전출 네트워크
age_net(30)
# 40대 인구 전출 네트워크
age_net(40)
# 50대 인구 전출 네트워크
age_net(50)
- 20~30대에서는 활발하던 인구이동이 4-50대 이상으로 갈수록 지역구를 잘 벗어나지 않는 특성을 보임
3.5. 서울시 지역구 전입/전출비율
#전입 데이터 서울시 지역구별 집계인구
IN_CTNCD_POP <- SEOUL_MOVE_TYP1 %>%
group_by(CUR_CTNCD) %>%
filter(PRV_CTNCD!=CUR_CTNCD)%>%
summarise_at("POP_CNT", sum, na.rm=TRUE)
#전출 데이터 서울시 지역구별 집계인구
OUT_CTNCD_POP <- SEOUL_MOVE_TYP2 %>%
group_by(CUR_CTNCD) %>%
filter(CUR_CTNCD!=AFT_CTNCD)%>%
summarise_at("POP_CNT", sum, na.rm=TRUE)
#전입/전출 데이터를 현재 지역구 기준으로 병합
INOUT_CTNCD_POP<- merge(IN_CTNCD_POP,
OUT_CTNCD_POP,
by=c("CUR_CTNCD"),
suffixes=c(".MV_TYP1", ".MV_TYP2"))
INOUT_CTNCD_POP <- merge(INOUT_CTNCD_POP, area_df,
by.x="CUR_CTNCD", by.y="SIG_CD")
INOUT_CTNCD_POP <- as.data.table(INOUT_CTNCD_POP)
#전입-전출의 차이를 계산
INOUT_CTNCD_POP$MV_DIFF<- INOUT_CTNCD_POP$POP_CNT.MV_TYP1 -
INOUT_CTNCD_POP$POP_CNT.MV_TYP2
#전입-전출의 차의 증감 상태를 산출
INOUT_CTNCD_POP$status <- factor(ifelse(INOUT_CTNCD_POP$MV_DIFF<0, "감소", "증가"))
INOUT_CTNCD_POP
CUR_CTNCD | POP_CNT.MV_TYP1 | POP_CNT.MV_TYP2 | SIG_KOR_NM | MV_DIFF | status |
---|---|---|---|---|---|
11110 | 8764 | 10771 | 종로구 | -2007 | 감소 |
11140 | 7928 | 9483 | 중구 | -1555 | 감소 |
11170 | 15299 | 14996 | 용산구 | 303 | 증가 |
11200 | 23974 | 20474 | 성동구 | 3500 | 증가 |
11215 | 23541 | 23941 | 광진구 | -400 | 감소 |
11230 | 21752 | 24577 | 동대문구 | -2825 | 감소 |
11260 | 19967 | 15211 | 중랑구 | 4756 | 증가 |
11290 | 23737 | 27918 | 성북구 | -4181 | 감소 |
11305 | 16521 | 17564 | 강북구 | -1043 | 감소 |
11320 | 15278 | 14421 | 도봉구 | 857 | 증가 |
Next
123
Previous
1-10 of 25 rows
지역구 전입/전출 현황
지역구 전입/전출 현황(지도)
- 지역구 내로의 전입/전출 제외
- 송파구>은평구>강서구의 순으로 전입 인구수가 상승세
- 강남구>서초구>성북구 순으로 전출 인구수가 감소세
3.6. 서울시 연령별 소득 및 소비 현황
#현재 지역구의 평균월소득, 중위월소득, 평균신용카드소비 재집계
SEOUL_CUR_INCOME<- SEOUL_SUMM_TYP2 %>%
group_by(CUR_CTNCD, AGE_BIN) %>%
summarise_at(c("AVG_MON_INCOME", "MED_MON_INCOME","AVG_MON_CARDSPND"),
mean, na.rm=TRUE)
#현재의 사용자 시군구 코드 병합
SEOUL_CUR_INCOME <- merge(seoulDF, SEOUL_CUR_INCOME,
by.x="SIG_CD", by.y="CUR_CTNCD", all.x=T)
SEOUL_CUR_INCOME <- SEOUL_CUR_INCOME[order(SEOUL_CUR_INCOME$id,
SEOUL_CUR_INCOME$order), ]
SEOUL_CUR_INCOME <- as.data.table(SEOUL_CUR_INCOME)
#천단위 -> 만단위로 단위 조정
SEOUL_CUR_INCOME$AVG_MON_INCOME <- SEOUL_CUR_INCOME$AVG_MON_INCOME/10
SEOUL_CUR_INCOME$MED_MON_INCOME <- SEOUL_CUR_INCOME$MED_MON_INCOME/10
SEOUL_CUR_INCOME$AVG_MON_CARDSPND <- SEOUL_CUR_INCOME$AVG_MON_CARDSPND/10
서울시 지역구내 월별 중위소득집계
SEOUL_CUR_INCOME$AGE_BIN <- factor(SEOUL_CUR_INCOME$AGE_BIN)
levels(SEOUL_CUR_INCOME$AGE_BIN) <- paste0("AGE = ", levels(SEOUL_CUR_INCOME$AGE_BIN))
ggplot(data = SEOUL_CUR_INCOME ,
mapping = aes(x = long,
y = lat,
group = group)) +
geom_polygon(mapping = aes(fill =MED_MON_INCOME),
color = 'black') +
#theme_bw() +
coord_fixed() +
scale_fill_gradient(low = 'white', high = 'red') +
facet_wrap(~AGE_BIN) + my_theme
- 20-30대 까지는 지역별 소득 편차가 있지 않은편, 연령이 증가할수록 편차 발생
- 소득의 경우 극단값의 영향이 크므로 중위수의 값으로 산출
- 20대에는 가장 낮은 월소득, 30-50대에 안정적인 소득 분포, 60-70대에는 거의 낮은 소득
- 40-50대에 강남,서초,송파,양천,노원 등 일부 지역이 월별 고소득자 분포
서울시 지역구내 월별 신용카드 소비 분석
ggplot(data = SEOUL_CUR_INCOME ,
mapping = aes(x = long,
y = lat,
group = group)) +
geom_polygon(mapping = aes(fill =AVG_MON_CARDSPND),
color = 'black') +
#theme_bw() +
coord_fixed() +
scale_fill_gradient(low = 'white', high = 'red') +
facet_wrap(~AGE_BIN)+ my_theme
- 20대에는 낮은 소득에 비해 신용카드소비량이 다소 높음.