• Home

전세가율 시각화 분석

전세가율이 높아지고 있다고 많은 미디어에서 이야기 하고 있다. 따라서 실제 전세가율이 시간이 지나면서 어떻게 변해가는지 데이터를 통해서 확인해 보고자 한다.

이를 위해서는 국토교통부 실거래가사이트에서 전세/매매 관련 데이터를 가져와야 되는데 크롤링 하는 방법은 필자가 정리해둔 국토교통부 실거래가 데이터 크롤링 코드를 참고해서 수집하면 된다.

suppressPackageStartupMessages({
library(data.table)
library(dplyr)
library(ggplot2)
library(lubridate)
library(extrafont)
library(stringr)
})

theme_set(theme_gray(base_family = "UnBatang"))

#전세/매매 데이터 로딩 
load("result_sales_dt.RData")
load('result_rents_dt.RData')

가져온 전세/월세 데이터의 얼개는 아래와 같다.

## Observations: 2362202
## Variables:
## $ si_gun_gu         (chr) " 서울특별시 강남구 개포동", " 서울특별시 강남구...
## $ m_bun             (dbl) 12, 12, 12, 12, 12, 12, 12, 1...
## $ s_bun             (dbl) 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ dangi             (chr) "대청", "대청", "대청", "대청", "대청",...
## $ type_of_rent      (chr) "월세", "전세", "전세", "전세", "전세",...
## $ area              (dbl) 39.53, 51.12, 60.00, 51.12, 5...
## $ cont_date         (chr) "21~31", "11~20", "21~31", "1...
## $ base_price        (dbl) 17000, 22000, 24000, 21000, 2...
## $ monthly_charge    (dbl) 15, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ floor             (dbl) 6, 4, 12, 2, 2, 5, 1, 1, 12, ...
## $ year_of_construct (dbl) 1992, 1992, 1992, 1992, 1992,...
## $ road_nm           (chr) "개포로109길", "개포로109길", "개포로109...
## $ region            (chr) "서울", "서울", "서울", "서울", "서울",...
## $ yyyymm            (chr) "201101", "201101", "201101",...
## $ typenm            (chr) "전월세아파트", "전월세아파트", "전월세아파트",...
## $ mm                (chr) "01", "01", "01", "01", "01",...
## $ qrt               (chr) "Q1", "Q1", "Q1", "Q1", "Q1",...
## $ yyyyqrt           (fctr) 2011Q1, 2011Q1, 2011Q1, 2011...
## $ yyyy              (fctr) 2011, 2011, 2011, 2011, 2011...

type_of_rent 필드에서 전세인 경우만 사용할 것이며, base_price가 전세가가 된다. 나머지 필드는 매매 데이터와 비슷하니 별도 설명은 하지 않겠다.

두가지 데이터를 결합하기 위해서는 Join이라는 데이터 결합 방식을 사용해야 된다. 간단하게 설명하면 두 데이터셋에서 지정된 필드의 값이 같은 경우 지정된 필드들을 하나의 데이터로 결합하는 것을 의미한다.

조인(Join)을 수행할시 정확하게 하기 위해 주소, 년도/월, 층, 면적까지 맞추도록 하자!

참고로 전세 데이터는 2011년도 데이터부터 존재한다. 따라서 전세가율은 2011년도부터 확인 가능하다.

rents <- result_rents_dt[type_of_rent %chin% '전세']

rent_sales <- rents %>% 
  inner_join(result_sales_dt, by=c('si_gun_gu', 'm_bun', 's_bun', 'dangi','area', 'yyyymm', 'floor')) %>% 
  data.table


ggplot(rent_sales %>% sample_frac(0.5), aes(price, base_price, colour=yyyy.x)) + geom_point(alpha=0.7) + stat_smooth(method='gam', formula = y~ s(x, bs='cs'), size=1.7) + scale_color_brewer('yyyy',palette = "Set1") + xlab('매매가(만원)') + ylab('전세가(만원)')

전국 매매가 대비 전세가

년도별 산점도와 더불어 데이터가 보여주는 비선형적인 패턴도 충분히 보여주기 위해 각 년도별 비선형 회귀모형을 만들어 그래프로 표현해 주었다.

좀더 공평하게 보기 위해 각 년도별 Q1 데이터만 시각화 해봤다. 확인해보면 2014년의 전세가율과 상당히 유사하다는 것을 알 수 있다.

ggplot(rent_sales[qrt.y %chin% 'Q1'], aes(price, base_price, colour=yyyy.x)) + geom_point(alpha=0.7) + stat_smooth(method='gam', formula = y~ s(x, bs='cs'), size=1.7) + scale_color_brewer('yyyy',palette = "Set1") + xlab('매매가(만원)') + ylab('전세가(만원)') + ggtitle('Q1 시각화')

plot of chunk q1

몇몇 미디어에서는 수도권의 전세가율에 대해서 이야기 하고 있는데, 같은 방식으로 경기지역만 아래 그림에서 보는바와 같이 확인해보면 경기지역의 2015년 전세가율이 사상 최대라는게 과장된 이야기는 아니라는 것을 알 수 있다.

ggplot(rent_sales[region.x %chin% c('경기')] %>% sample_frac(0.6) , aes(price, base_price, colour=yyyy.x)) + geom_point() + stat_smooth(method='gam', formula = y~ s(x, bs='cs'), size=1.5) + scale_color_brewer('yyyy',palette = "Set1") + facet_wrap(~region.x,scale='free', ncol=3) + xlab('매매가(만원)') + ylab('전세가(만원)') 

경기지역 매매가와 전세가

위 그림의 경우 매매 가격에 따른 전세금의 가격에 따른 추이를 대략적으로 가늠해 볼 수 있으나, 정확한 전세가율의 분포를 확인하기는 어렵다. 따라서 전세가율을 계산해 단변량에 대한 분포를 확인하도록 하겠다.

아래 그림은 전세가를 매매가로 나눈 전세가율 자체의 상자그림(boxplot) 보여준다. 상자그림은 박스를 해석하는게 중요한데, 전통적인 평균 분산을 매핑시켜 보면 좀 쉽게 접근이 가능하다. 상자의 중간에 있는 평행선을 중앙값(median)이라 하며 값을 순서대로 정렬해서 중간에 있는 값을 의미한다. 그리고 IQR은 25퍼센타일과 75퍼센타일의 차이를 의미하는데, 예를 들어 총 100개의 숫자를 정렬했을때 25번째 있는 값과 75번째 있는 값의 차이 구간을 나타낸다. 중앙값은 평균과 유사한 역할을 하며, IQR은 분산이나 표준편차와 같은 역할을 수행한다고 보면 된다. 정렬된 값을 기준으로 나타낸 통계량이기 때문에 이상치(outlier)에 좀더 강건하다고 알려져 있다. 좀더 상세한 내용을 알고 싶은 독자는 위키피디어(http://en.wikipedia.org/wiki/Box_plot)를 참고하길 바란다.

invisible(rent_sales[,rent_ratio:=base_price/price])
ggplot(rent_sales, aes(region.x, rent_ratio)) + geom_boxplot(aes(fill=yyyy.x),outlier.size=0.5) + scale_y_continuous(breaks=seq(0,2.0, by=0.1)) + xlab("지역") + ylab('전세가율') + scale_fill_discrete('년도')

지역별 연도별 전세율

위 상자그림의 중앙값과 IQR을 참고해서 살펴보면 대부분 지역의 년도별 전세가율은 상승추세에 있는 것을 알 수 있다.
서울은 전세가율(중앙값)이 70%에 근접하고 있고, 경기도는 70%를 넘어가고 있는 것을 볼 수 있다. 2011년 제주도의 전세가율은 데이터에 뭔가 문제가 있는 것으로 보인다.

과연 전세가율이 80%(0.8)을 넘어서 100%까지 갈 수 있을까?

결과적으로 이야기하면 알수 없다!가 정답이 될 것이다.

그러나 데이터에서 힌트를 얻을 수는 있는데, 도표를 자세히 보면 전세가율 상승 추세가 꺽인 지역이 보일 것이다. 좀더 장기간의 데이터가 있었다면 시간적으로 선행 패턴을 보이는 지역을 기준으로 그 패턴을 따라가는 지역에 대해서 예측을 수행할 수 있을거라는 상상도 해본다. 물론 교차상관(cross correlation)과 같은 통계량에 대한 검증이 필요하지만 말이다.

seouls <- rent_sales[si_gun_gu %like% '서울특별시']

invisible(seouls[, gu:=sapply(str_trim(si_gun_gu),function(x){str_split_fixed(x,pattern = ' ', n=3)[1,2]})])

ggplot(seouls, aes(gu, rent_ratio)) + geom_boxplot(aes(fill=yyyy.x),outlier.size=0.5) + scale_y_continuous(breaks=seq(0,2.0, by=0.1)) + xlab("지역") + ylab('전세가율') + scale_fill_discrete('년도') + theme(axis.text.x=element_text(angle=45))

plot of chunk unnamed-chunk-6

위에서는 서울 지역내 구단위 전세가율에 대한 분포를 보여주는데, 예상했던 대로 전 구에서 전세가율이 상승 추이에 있다는 것을 볼 수 있으나, 강남, 강동구의 경우 각 년도별 분산이 크기 때문에 상승 추이에 있다고 보기 힘들다. 전세가율의 변동이 크다는건 매매가의 변동이 커서 그런건지 전세가의 변동이 큰 이유인지 확인이 필요하지만 전세가율로만 볼때 강남, 강동은 매우 변동이 큰 지역이라 볼 수 있다. 이 부분에 대해서는 강남의 대표적인 아파트 단지 한곳을 다음회에 상세하게 분석해 보면서 확인해볼 예정인데, 생각해 볼 수 있는 시나리오로는 학기초의 전세가와 학기중의 전세가의 차이가 커서 이런 현상이 일어날 수 있지 않을까 하는 예상을 해본다.

전세가율에 대해서 정리를 해보면 아래와 같다.

  1. 전세가율 상승은 전국적인 현상이라 볼 수 있다.
  2. 전세가율 상승은 진행되고 있으나 과거만큼 추이 상승이 크지 않다.
  3. 상승 추이는 수도권 이내가 가장 뚜렸하다.
  4. 서울시 전세가율 추이를 볼때 특징적으로 다른 몇개의 구가 존재하고 있다.

다음번에는 서울시 전세가율 특징이 다른 몇개 아파트 단지를 선택해 상세 분석을 수행해 볼 예정이다.

회사 사보 인터뷰

오랜만에 블로그 워드프레스 웹 에디터로 글을 써본다.

얼마전에 회사 사보에서 인터뷰를 했는데(처음엔 그룹 사보인줄 알았다), 관련 글을 올려도 큰 문제 없다는 이야기를 듣고 이렇게 인터뷰 글을 올려본다(백업용이다 ^^).

STK 마켓탑

회사 내에서는 마켓탑이라는 호칭으로 한 석달전에 전사 세미나를 하고 그걸 녹화한 방송이 몇일 후 전사 방송으로 송출되는 사건이 있었는데, 아마도 이 인터뷰 글이 그 여파의 마지막이지 않을까 생각해 본다.

탑이라는 호칭은 정말 마케팅적이고, 거품이 많은 단어이다. 그리고 설령 지금 내가 탑이라는게 사실이라더라도 이젠 결국 내려올 수 밖에 없다는 이야기인데, 아직 이 다음이 뭔지 고민조차 해보지 않은 나로서는 참으로 어려운 단어이기도 하다.

결국 외면의 기준은 적당하게 내버려 두고 내면의 기준을 탄탄히 만드는게 중요한 시점이지 않을까 생각해 본다.

비선형 모형과 추세 분석(아파트 매매 데이터 기반)

지난번 포스팅을 통해서 얻은 데이터와 그 이전 포스팅의 아파트 매매가에 미치는 층수, 크기, 년도 효과에 대한 분석의 후속 분석으로 같은 데이터를 기반을 하는 분석이지만 2015년 Q1의 데이터가 어느정도 모였으니 이의 가격동향과 더불어 다중 회귀모형의 비선형적인 효과를 좀더 다른 방식의 알고리즘으로 모델링 해보고 시각화 해보는 과정을 거쳐보도록 하겠다.

참고로, 분석을 위해 2015년 2월까지의 아파트 매매 데이터를 다시 크롤링했다.

노파심에서 이야기 하지만, 이 분석은 부동산에 전혀 지식이 없는 한 개인이 내가 살고 있는 아파트 단지와 근처 몇몇 단지를 분석한 결과이므로 확대 해석은 매우 위험한 생각이라 말씀드리고 싶다. 그저 생활 데이터 분석의 하나일 뿐이다.

suppressPackageStartupMessages(
{
library(data.table)
library(mgcv)
library(party)
library(randomForest)
library(ggplot2)
library(dplyr)
library(extrafont)
library(randtests)
})

#http://freesearch.pe.kr/archives/4298 에서 만든 데이터를 로딩한다. 
load('result_sales_dt.RData')

setnames(result_sales_dt, 1:10,c('si_gun_gu', 'm_bun', 's_bun', 'dangi', 'area','cont_date', 'price', 'floor', 'year_of_construct', 'road_nm'))

result_sales_dt[,price:=as.numeric(price)]
result_sales_dt[,floor:=as.numeric(floor)]
result_sales_dt[,mm:=substr(yyyymm, 5,6)]
result_sales_dt[between(as.numeric(mm), 1, 3), qrt:='Q1']
result_sales_dt[between(as.numeric(mm), 4, 6), qrt:='Q2']
result_sales_dt[between(as.numeric(mm), 7, 9), qrt:='Q3']
result_sales_dt[between(as.numeric(mm), 10, 12), qrt:='Q4']
result_sales_dt[,yyyyqrt:=paste0(substr(yyyymm, 1,4), qrt)]
result_sales_dt[,yyyy:=factor(substr(yyyymm, 1,4))]
#이전 포스팅과 다르게 쿼터로 날짜는 자른다. 
result_sales_dt[,yyyyqrt:=factor(yyyyqrt)]


my_apt <- result_sales_dt[si_gun_gu %chin% " 서울특별시 관악구 신림동" & m_bun == 1730]

ggplot(my_apt, aes(floor, price)) + geom_point(aes(colour=yyyy)) 

plot of chunk unnamed-chunk-1

일단 층별 매매가를 보면 위와 같은 비선형적인 패턴이 보인다. 익히 알고 있는 로열층이 가격대가 높은것을 실제 데이터를 통해 확인이 가능하다.

이런 사전지식 하에서 이전 포스팅에서 했던 층변수에 2차 함수를 할당한 회귀모형 시각화를 확인해 보자.

#아웃라이어 레코드 제거 (잔차 분석 참고 ...)
my_apt <- my_apt[-c(54,67,202)]

lm_mdl <- lm(price ~ yyyyqrt + I(floor^2) + floor  + area, data=my_apt)

#지난번 하지 않았던 오차상관성 검정... 상관성은 없다고 봐도 무방하다. 
runs.test(resid(lm_mdl))
## 
##  Runs Test
## 
## data:  resid(lm_mdl)
## statistic = 1.0647, runs = 226, n1 = 214, n2 = 214, n = 428,
## p-value = 0.287
## alternative hypothesis: nonrandomness
levelss <- levels(factor(my_apt$yyyyqrt))

aggrs_fun <- function(floor, area, mdls){
  predict(mdls, data.table(yyyyqrt=factor(rep("2015Q1"),levels=levelss), floor=floor, area=area))
}


floor_seq <- seq(1,24, length=30)
area_seq <- seq(59,140, length=30)

persp(floor_seq,area_seq, z=outer(floor_seq,area_seq, aggrs_fun, lm_mdl), col="green", ticktype="detailed",shade=TRUE, theta=-25,phi = 5, xlab="floor", ylab="area", zlab = "price")

plot of chunk _lm

나쁘지 않아 보인다. 사실 다중 회귀 모형에서 2차 함수 형태를 직접 데이터 시각화를 통해서 발견해 채용한 그 과정이 흥미로웠다고 생각한다.

regression tree를 동일한 방식으로 살펴보자!

ctree_mdl <- ctree(price ~ yyyyqrt + floor + area, data=my_apt)

persp(floor_seq,area_seq, z=outer(floor_seq,area_seq, aggrs_fun, ctree_mdl), col="green", ticktype="detailed",shade=TRUE, theta=-25,phi = 5, xlab="floor", ylab="area", zlab = "price")

plot of chunk tree

물론 예상했지만 거의 비선형적인 패턴을 추출하지 못한것으로 보인다. 왜냐면 6층부터 24층까지 동일한 층수 효과를 적용했기 때문이다.

rf_mdl <- randomForest(price ~ yyyyqrt + floor  + area, data=my_apt)


persp(floor_seq,area_seq, z=outer(floor_seq,area_seq, aggrs_fun, rf_mdl), col="green", ticktype="detailed",shade=TRUE, theta=-25,phi = 5, xlab="floor", ylab="area", zlab = "price")