일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | |||
5 | 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | 17 | 18 |
19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 | 27 | 28 | 29 | 30 | 31 |
- 서울시장
- 안철수
- 회고
- 신입개발자
- 구글트렌드
- 2021년회고
- 국민의힘경선
- 데이터과학자의일
- 데이터분석가
- 데이터분석공부
- 2021년의 #봄여름가을겨울
- 데이터분석가준비
- 360시간만에개발자되기
- 네이버트렌드
- 주니어개발자
- 개발자면접
- 데이터과학자진로
- 글또회고
- 데이터분석
- 라이브코딩테스트
- 데이터시각화
- 새파란
- 글또6기회고
- 박영선
- 360시간만에개발자
- 국회데이터시각화
- 개발자취업
- 스타트업독서노트
- 데이터분석가채용
- 로버트마틴
- Today
- Total
NEWBLUE's
[부동산 데이터 분석] 데린이의 서울 내 집 장만 프로젝트 (1) - pandas와 친해지기 본문
안녕하세요. 새파란입니다. 천천히 데이터 시각화 공부를 시작하려고 합니다.
어떤 데이터로 시작을 할까 하다가, 만인의 관심! 부동산 데이터로 결정을 내렸습니다.
월 10만 원 내외 기숙사에 살다가, 이제 몇십 만원씩 월세를 내고 있으니 '내 집 장만'에 관심을 가지지 않을 수가 없었네요ㅎㅎ
천천히 수도권의 다양한 데이터를 보면서 부동산과 친해지는(?) 시간을 가져 보려고 합니다.
주택에는 단독주택, 아파트, 연립주택 등 다양한 종류가 있습니다.
먼저 국토교통부 실거래가 공개시스템에서 현재 제가 살고 있는 곳인 연립/다세대 주택의 2020년 1월부터 10월까지의 통계를 다운로드하였습니다. (엑셀에서 CSV UTF-8 형식으로 저장해야 깨지지 않아요)
데이터 가져오기
먼저 데이터를 살펴볼까요?
import pandas as pd
home = pd.read_csv('house_data.csv')
home.head(2)
시군구 | 번지 | 본번 | 부번 | 건물명 | 전월세구분 | 전용면적(㎡) | 계약년월 | 계약일 | 보증금(만원) | 월세(만원) | 층 | 건축년도 | 도로명 | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 서울특별시 강남구 개포동 | 1163-4 | 1163 | 4 | (1163-4) | 전세 | 21.88 | 202002 | 27 | 16,000 | 0 | 5 | 2013 | 논현로 10 |
1 | 서울특별시 강남구 개포동 | 1163-4 | 1163 | 4 | (1163-4) | 월세 | 13.56 | 202007 | 9 | 6,000 | 25 | 2 | 2013 | 논현로 10 |
우선 필요한 카테고리만 골라야 할 것 같아요.
hdata = home[['시군구','전월세구분','전용면적(㎡)','계약년월','계약일','보증금(만원)','월세(만원)','층','건축년도']]
hdata.head(2)
시군구 | 전월세구분 | 전용면적(㎡) | 계약년월 | 계약일 | 보증금(만원) | 월세(만원) | 층 | 건축년도 | |
---|---|---|---|---|---|---|---|---|---|
0 | 서울특별시 강남구 개포동 | 전세 | 21.88 | 202002 | 27 | 16,000 | 0 | 5 | 2013 |
1 | 서울특별시 강남구 개포동 | 월세 | 13.56 | 202007 | 9 | 6,000 | 25 | 2 | 2013 |
왠지 '구'를 분리하면 나중에 쓸 일이 많을 것 같아, 분리해봅시다.
hdata['구'] = hdata['시군구'].str.split(' ').str[1]
그랬더니 아래와 같은 에러가 발생했어요. 당황하지 말고 오류 메세지를 구글에 검색해봅니다.
<ipython-input-6-b9ac15e704a3>:1: SettingWithCopyWarning:
A value is trying to be set on a copy of a slice from a DataFrame.
Try using .loc[row_indexer,col_indexer] = value instead
See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy
hdata['구'] = hdata['시군구'].str.split(' ').str[1]
오류 해결 척척박사님에 따르면 위와 같이 "chained" assignments에 경고를 주는 걸로 되어있네요. 하지만 링크의 예에도 있듯이, 저희는 걱정하지 않아도 될 것 같네요.
pd.options.mode.chained_assignment = None # default='warn'
위와 같은 옵션을 추가하면 더 이상 warning이 뜨지 않습니다.
데이터 살펴보기
그럼 드디어 첫 번째 그래프를 그려볼까요?
복잡한 라이브러리를 사용하지 말고 바로 그릴 수는 없는지 찾아보니 (역시나) pandas.Dataframe.plot()을 편하게 사용할 수가 있네요.
라이브러리 문서를 참조하니, plotting.backend 옵션에 따라 어떻게 그래프를 그리는지가 달라진다고 하네요. 기본적으로는 유명한 matplotlib 가 사용된다고 합니다.
전세 / 월세 비중이 궁금하니, 그래프를 그려봅시다.
hdata.groupby('전월세구분')['시군구'].count().plot.pie()
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:238: RuntimeWarning: Glyph 49884 missing from current font.
font.set_text(s, 0.0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:238: RuntimeWarning: Glyph 44400 missing from current font.
font.set_text(s, 0.0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:238: RuntimeWarning: Glyph 44396 missing from current font.
font.set_text(s, 0.0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:238: RuntimeWarning: Glyph 50900 missing from current font.
font.set_text(s, 0.0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:238: RuntimeWarning: Glyph 49464 missing from current font.
font.set_text(s, 0.0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:238: RuntimeWarning: Glyph 51204 missing from current font.
font.set_text(s, 0.0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:201: RuntimeWarning: Glyph 49884 missing from current font.
font.set_text(s, 0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:201: RuntimeWarning: Glyph 44400 missing from current font.
font.set_text(s, 0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:201: RuntimeWarning: Glyph 44396 missing from current font.
font.set_text(s, 0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:201: RuntimeWarning: Glyph 50900 missing from current font.
font.set_text(s, 0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:201: RuntimeWarning: Glyph 49464 missing from current font.
font.set_text(s, 0, flags=flags)
/usr/local/lib/python3.8/site-packages/matplotlib/backends/backend_agg.py:201: RuntimeWarning: Glyph 51204 missing from current font.
font.set_text(s, 0, flags=flags)
역시나 잔뜩 warning이 뜨는군요. 뭔가 한글이 네모네모처럼 나온 걸 보니 한글과 관련된 것 같아요. 역시 당황하지 말고 구글링을 해봅니다.
그 결과, 아래 옵션을 추가하면 된다고 하네요.
import matplotlib.pyplot as plt
from matplotlib import rc
rc('font', family='AppleGothic')
plt.rcParams['axes.unicode_minus'] = False
다시 해봐야겠죠?
hdata.groupby('전월세구분')['시군구'].count().plot.pie()
드디어 정상적인 그래프가 나왔습니다! 25%~30% 정도 되어 보이니, 생각보다 월세를 내는 분들이 적군요. (그게 바로 접니다)
월세 분포 살펴보기
month_rent = hdata[hdata['전월세구분'] == '월세']
month_rent['월세(만원)'].plot()
month_rent['월세(만원)'].plot()
음, 이건 제가 원했던 데이터가 아니네요. 생각해보니 저는 월세의 분포를 보고 싶어요!
month_rent['월세(만원)'].plot.hist()
음, '대부분의 사람들이 100만 원 이하의 월세를 살고 있다'는 너무 당연한 사실 같네요. 조금 범위를 좁혀야겠어요.
그리고 10만 원 단위로 맞춰서 볼 수 있게, bins조건을 추가합니다.
month_rent_part = month_rent[month_rent['월세(만원)'] <= 150]
month_rent_part['월세(만원)'].plot.hist(bins=15)
전세 분포 살펴보기
이번엔 전세를 볼까요?
full_rent = hdata[hdata['전월세구분'] == '전세']
full_rent['보증금(만원)'] = full_rent['보증금(만원)'].str.replace(',', '').astype(float)
full_rent_part = full_rent[full_rent['보증금(만원)'] <= 60000]
full_rent_part['보증금(만원)'].plot.hist(bins=12)
1억 5천~2억 5천 사이의 집들이 가장 많네요. 내년에 전세로 갈아타고 싶었는데...... 일단 그렇군요.
언제 원룸 계약이 이루어질까요?
groupby 하고 한 열(이 경우 '층')을 선택하는 꼼수 아닌 꼼수(?)를 사용해보았습니다.
hdata.groupby('계약년월').count()['층'].plot()
hdata.groupby('계약일').count()['층'].plot()
층과 건축년도에도 경향성이 있을까요?
hdata[hdata['층'] < 10].groupby('층').count()['계약일'].plot()
층의 경우 2~3층이 1등을 차지했습니다. 전혀 놀랍지 않은 사실
hdata[hdata['건축년도'] > 1980].groupby('건축년도').count()['계약일'].plot()
최근 들어 다시 증가하는 추세네요.
몇 평에 사는 사람이 제일 많을까요?
hdata['전용면적(㎡)'].plot.hist(bins=12)
전용 면적으로 계산해보니 조금 헷갈려서, 평으로 바꿔봤습니다.
hdata['평'] = hdata['전용면적(㎡)'] / 3.30579
hdata['평'].plot.hist(bins=8)
서울에서 평균 월세/보증금이 가장 높은 곳은?
month_rent.groupby('구').mean().sort_values('월세(만원)',ascending=False)
전용면적(㎡) | 계약년월 | 계약일 | 월세(만원) | 층 | 건축년도 | |
---|---|---|---|---|---|---|
구 | ||||||
강남구 | 33.757174 | 202005.049087 | 15.312146 | 66.948395 | 2.892385 | 2005.920705 |
서초구 | 33.020288 | 202005.076142 | 15.404399 | 59.110829 | 3.059222 | 2009.244501 |
중구 | 30.784808 | 202004.628205 | 13.555556 | 52.871795 | 3.166667 | 2008.260684 |
용산구 | 34.917637 | 202004.720430 | 15.120968 | 52.502688 | 2.763441 | 2006.451613 |
마포구 | 28.441464 | 202004.991977 | 15.237053 | 49.024070 | 2.989059 | 2007.615609 |
성동구 | 31.118512 | 202005.093284 | 15.686567 | 48.283582 | 3.190299 | 2006.615672 |
종로구 | 36.074582 | 202004.643636 | 15.330909 | 47.949091 | 2.694545 | 2001.745455 |
송파구 | 33.871557 | 202005.138800 | 15.791265 | 47.208735 | 3.105841 | 2008.497588 |
광진구 | 31.282165 | 202004.988679 | 15.722642 | 46.021698 | 3.262264 | 2011.797170 |
동작구 | 31.230969 | 202004.876005 | 15.482204 | 45.127440 | 3.315729 | 2010.173364 |
강동구 | 34.364117 | 202005.189736 | 15.545101 | 44.918351 | 3.600311 | 2011.641524 |
은평구 | 37.712440 | 202005.135780 | 15.502752 | 44.807339 | 3.429358 | 2007.439450 |
동대문구 | 33.436415 | 202004.546125 | 14.929889 | 44.295203 | 4.103321 | 2011.407749 |
중랑구 | 35.340498 | 202005.223903 | 15.384266 | 44.163389 | 3.806354 | 2012.266263 |
서대문구 | 30.539418 | 202004.587171 | 16.848684 | 43.973684 | 3.159539 | 2007.537829 |
강서구 | 36.210009 | 202004.972669 | 16.249196 | 43.215434 | 3.498392 | 2008.263666 |
강북구 | 38.144917 | 202005.110818 | 15.918206 | 43.205805 | 3.189974 | 2009.263852 |
관악구 | 29.720329 | 202004.869328 | 15.393829 | 43.164247 | 3.733212 | 2008.520871 |
양천구 | 37.063173 | 202005.433018 | 16.198917 | 43.017591 | 2.971583 | 2006.399188 |
영등포구 | 27.592072 | 202004.986559 | 17.061828 | 42.647849 | 4.206989 | 2010.231183 |
성북구 | 34.362805 | 202004.658025 | 15.259259 | 40.811111 | 3.251852 | 2011.377778 |
금천구 | 35.634325 | 202005.091787 | 14.538647 | 40.330918 | 3.727053 | 2012.562802 |
도봉구 | 40.603408 | 202005.049315 | 15.857534 | 39.413699 | 2.898630 | 2004.989041 |
구로구 | 40.856447 | 202005.032423 | 15.646758 | 38.674061 | 3.319113 | 2006.141638 |
노원구 | 31.542765 | 202004.615385 | 15.526316 | 37.000000 | 3.210526 | 2010.331984 |
역시 강남구와 서초구였습니다! (눈물이 앞을 가립니다)
마지막인 노원구와는 대략 30만 원 정도 차이가 나네요.
full_rent.groupby('구').mean().sort_values('보증금(만원)',ascending=False)
전용면적(㎡) | 계약년월 | 계약일 | 보증금(만원) | 월세(만원) | 층 | 건축년도 | |
---|---|---|---|---|---|---|---|
구 | |||||||
서초구 | 36.114510 | 202005.286422 | 15.692943 | 29371.113496 | 0.0 | 3.438300 | 2011.562526 |
강남구 | 34.223996 | 202005.155526 | 15.442068 | 27462.081996 | 0.0 | 3.213012 | 2009.331996 |
광진구 | 35.320170 | 202005.150503 | 15.468410 | 22846.198390 | 0.0 | 3.435412 | 2012.957344 |
송파구 | 36.764483 | 202005.273191 | 15.616681 | 22459.128000 | 0.0 | 3.253787 | 2009.951319 |
강동구 | 34.766762 | 202005.208399 | 15.798688 | 22184.993176 | 0.0 | 3.932021 | 2013.491076 |
동작구 | 37.998278 | 202005.303562 | 15.625199 | 22081.632111 | 0.0 | 3.069644 | 2009.972355 |
영등포구 | 30.311376 | 202005.218947 | 16.088421 | 22025.666667 | 0.0 | 5.041404 | 2014.564912 |
중구 | 32.623065 | 202005.651663 | 14.994129 | 21602.035225 | 0.0 | 3.590998 | 2011.825832 |
용산구 | 34.741185 | 202005.364910 | 15.601734 | 20725.323549 | 0.0 | 2.955304 | 2010.777852 |
중랑구 | 34.780398 | 202005.458398 | 15.629045 | 20562.058552 | 0.0 | 4.209938 | 2014.288906 |
마포구 | 33.706324 | 202005.214927 | 15.498618 | 20539.314098 | 0.0 | 3.242571 | 2009.294402 |
관악구 | 35.380694 | 202005.313999 | 16.088966 | 20531.428260 | 0.0 | 3.610118 | 2009.878761 |
금천구 | 34.836127 | 202005.618741 | 15.484979 | 20163.623033 | 0.0 | 4.258226 | 2013.208870 |
동대문구 | 34.802489 | 202005.073597 | 15.410304 | 19847.382705 | 0.0 | 3.729531 | 2012.433303 |
강서구 | 36.206088 | 202005.422924 | 15.969828 | 19483.287324 | 0.0 | 3.722386 | 2011.912953 |
성북구 | 38.541718 | 202005.144553 | 15.501807 | 19267.466185 | 0.0 | 3.149716 | 2011.997935 |
구로구 | 39.931736 | 202005.432403 | 15.858238 | 18900.731801 | 0.0 | 3.288998 | 2009.124247 |
성동구 | 34.884004 | 202005.114202 | 16.708638 | 18837.538799 | 0.0 | 3.496340 | 2006.869693 |
양천구 | 37.363237 | 202005.536746 | 16.145101 | 18419.795854 | 0.0 | 3.405465 | 2009.075691 |
종로구 | 40.941576 | 202005.051724 | 14.017241 | 18276.169951 | 0.0 | 2.603448 | 2003.283251 |
서대문구 | 39.640336 | 202005.084192 | 15.697595 | 18225.330756 | 0.0 | 3.042096 | 2007.662371 |
은평구 | 39.810937 | 202005.292192 | 15.860087 | 18199.978177 | 0.0 | 3.554316 | 2010.040737 |
강북구 | 41.865768 | 202005.474388 | 15.335189 | 16809.599109 | 0.0 | 3.153675 | 2008.924276 |
도봉구 | 41.454546 | 202005.465919 | 15.499569 | 16328.607420 | 0.0 | 3.270060 | 2008.427092 |
노원구 | 36.734702 | 202005.015949 | 16.192982 | 12722.290271 | 0.0 | 2.934609 | 2005.177033 |
보증금도 큰 차이가 없었습니다. 서초와 강남이 자리를 바꿨네요.
이번엔 서초구와 노원구는 1억 7천만 원 차이가 났습니다.
눈은 높았지만, 손이 아직 따라오지 못하고 있다
이렇게 궁금했던 연립/다세대 주택 부동산과 관련된 정보를 그래프로 나타냈습니다.
처음인 만큼, 아름답게 혹은 명확하게 그리려고 하기보단 일단 그리는 데에 초점을 두었답니다.
('사실 이 글은 헬스장 전단지에 나오듯이, 시각화 공부 Before를 위해서 작성되었습니다' )
그리고 다음과 같이 더 하고 싶은 일이 생겼습니다.
(1) 바로 위에 표에서 필요 없는 정보를 삭제하고, 시각화를 하면 참 좋겠죠? (변수가 2개로 늘어났습니다)
(2) 단독 주택뿐만 아닌 서울에 다양한 주택(단독주택, 아파트 등) 별로 비교를 해볼까요?
(3) 지도에다가 그려보면 더 좋겠죠?
드디어 집에서 굴러다니던 아래 책을 읽어볼 차례가 된 것 같네요. (다음 화에 계속됩니다)
|