서울시 거주자 인구이동 및 소비현황 시각화

분석 개요

  • 목적: 서울시 거주자의 인구이동 및 소비현황 시각화를 하고자 함

분석 데이터

  • 코리아크레딧뷰로(주)의 인구전입데이터
  • 코리아크레딧뷰로(주)의 인구전출데이터
  • 국토교통부의 시군구행정코드 및 경계지도 데이터(공공데이터)

분석 과정

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

10127.008637.580471FALSE10.1종로구Jongno-gu
110127.010037.5802811FALSE10.1종로구Jongno-gu
210127.011737.5815121FALSE10.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

111110종로구
233311140중구
425111350노원구

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

120191001000000120191011117401121511215860160
120191001000000120191011115301150011500530120
120191001000000120191011112151126011260520130

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

201720191001000000220191020171011680116806901111650
201720191001000000220191020171011320113205141111170
201720191001000000220191020171011290112905551111650

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

1111011110201913.7941796.235860.4706
1111011110303213.7352578.7941429.9412
1111011110403579.1183047.6761782.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

1111011110201574.8821502.471707.7353
1111011110302587.6762172.2651323.1176
1111011110403142.9412623.2941642.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

1111011110118628
1111011140467
1111011170498

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

종로구0127.008637.580471FALSE10.1Jongno-gu11110
종로구0127.010037.5802811FALSE10.1Jongno-gu11110
종로구0127.011737.5815121FALSE10.1Jongno-gu11110

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("서울시 지역구 인구 전출 빈도수")

3-1

#전체 전출을 빈번하게 하는 지도
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("서울시 지역구 인구 전출 빈도수")

3-2

지역구 전출 빈도수
#전체 전출을 빈번하게 하는 지도
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("서울시 지역구 전출 빈도수")

3-3

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("서울시 지역구 전출 빈도수")

3-4

  • 전입 전출 데이터는 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("강남구")

3-5

# 양천구 인구 전출 지도
area.out.plot("양천구")

3-6

# 서초구 인구 전출 지도
area.out.plot("서초구")

3-7

# 강서구 인구 전출 지도
area.out.plot("강서구")

3-8

# 송파구 인구 전출 지도
area.out.plot("송파구")

3-9

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")

3-10

  • 강남,송파,서초 /노원,성북,강북,중랑/광진,동대문,성동/관악,동작,마포, 영등포/ 서대문,은평,종로 등의 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

117102093974송파구
116202091364관악구
115002083038강서구
116802082750강남구
112902077560성북구
113502077081노원구
112302068836동대문구
115902065388동작구
114702063370양천구
113802062790은평구

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)

3-11

# 30대 인구 전출 네트워크
age_net(30)

3-12

# 40대 인구 전출 네트워크
age_net(40)

3-13

# 50대 인구 전출 네트워크
age_net(50)

3-14

  • 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

11110876410771종로구-2007감소
1114079289483중구-1555감소
111701529914996용산구303증가
112002397420474성동구3500증가
112152354123941광진구-400감소
112302175224577동대문구-2825감소
112601996715211중랑구4756증가
112902373727918성북구-4181감소
113051652117564강북구-1043감소
113201527814421도봉구857증가

Next

123

Previous

1-10 of 25 rows

지역구 전입/전출 현황

3-15

지역구 전입/전출 현황(지도)

3-16

  • 지역구 내로의 전입/전출 제외
  • 송파구>은평구>강서구의 순으로 전입 인구수가 상승세
  • 강남구>서초구>성북구 순으로 전출 인구수가 감소세

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

3-17

  • 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 

3-18

  • 20대에는 낮은 소득에 비해 신용카드소비량이 다소 높음.