未分類

用程式分析房地產可行嗎(2)房價分析

大家都在說房價市場恢復景氣,然而真的是這樣子嗎?
你有沒有覺得,怎麼每個人說的話都不一樣?
數據雖然都是實價登錄,但有些人就是看到漲,有些人就是看跌?
究竟誰說的對,還是必須要親自研究一下數據,才會知道

數據是拿來「調整」的?!

身為一個「曾經」產出學術文章寫手,就會知道這些數據是有很多「可以操作空間」
(這樣講對嗎?XD)
不要相信任何人幫你統計的數據
因為任何人的數據都有可能想達成某種目的
例如某人要增加流量和公信力,就可以危言聳聽一點,用數據製作房價都在下跌的結論
某房仲想要刺激房地產,就會製作止跌回升的訊號,

難道數據造假?!

不論上漲下跌,相信這些數據都是對的,
都是從政府的實價登錄而得到
但分析方式不同,就會產生不同的結果!

所以數據是用來「感覺」的,而不是單看少數「專家」的結論
只能多做一點實驗,盡量讓實驗客觀公正,

這篇文章總共分成三個部分:

  1. 獲取實價登錄
  2. 房價歷史走勢圖
  3. 房價分佈圖

所以接下來我們就用 Python 來跟大家一起分析實價登錄的資料吧!

取得實價登錄資料

首先跟上次一樣,
爬取了實價登入所有歷史數據,這次我們爬取csv檔:

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
import requests
import os
import zipfile
import time

def real_estate_crawler(year, season):
if year > 1000:
year -= 1911

# download real estate zip file
res = requests.get("https://plvr.land.moi.gov.tw//DownloadSeason?season="+str(year)+"S"+str(season)+"&type=zip&fileName=lvr_landcsv.zip")

# save content to file
fname = str(year)+str(season)+'.zip'
open(fname, 'wb').write(res.content)

# make additional folder for files to extract
folder = 'real_estate' + str(year) + str(season)
if not os.path.isdir(folder):
os.mkdir(folder)

# extract files to the folder
with zipfile.ZipFile(fname, 'r') as zip_ref:
zip_ref.extractall(folder)

time.sleep(10)

有了上述這個 function 我們可以將實價登錄資訊全部爬取下來:

1
2
3
4
5
6
7
8
9
10
real_estate_crawler(101, 3)
real_estate_crawler(101, 4)

for year in range(102, 108):
for season in range(1,5):
print(year, season)
real_estate_crawler(year, season)

real_estate_crawler(108, 1)
real_estate_crawler(108, 2)

下載完後,會看到每一年每一季的實價登錄資料夾
裡面有很多檔案,主要可以分成以下三種:

  • x_lvr_land_a:房屋買賣交易
  • x_lvr_land_b:新成屋交易
  • x_lvr_land_c:租房交易

其中 x 是一個英文字母,代表每個縣市,也就是你身份證字號的開頭
例如台北,就是「a」,新北市就是「f」,以此類推

讀取資料

接下來我們以台北市為例子,看看能不能找到台北市便宜的好房子,
首先我們將歷年資料都讀進來:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import os
import pandas as pd

# 歷年資料夾
dirs = [d for d in os.listdir() if d[:4] == 'real']

dfs = []

for d in dirs:
print(d)
df = pd.read_csv(os.path.join(d,'a_lvr_land_a.csv'), index_col=False)
df['Q'] = d[-1]
dfs.append(df.iloc[1:])

df = pd.concat(dfs, sort=True)

然而這些資訊還必須再經過處理,才會讓我們待會的資料分析更好下手

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# 新增交易年份
df['year'] = df['交易年月日'].str[:-4].astype(int) + 1911

# 不同名稱同項目資料合併
df['單價元平方公尺'].fillna(df['單價元/平方公尺'], inplace=True)
df.drop(columns='單價元/平方公尺')

# 平方公尺換成坪
df['單價元平方公尺'] = df['單價元平方公尺'].astype(float)
df['單價元坪'] = df['單價元平方公尺'] * 3.30579

# 建物型態
df['建物型態2'] = df['建物型態'].str.split('(').str[0]

# 刪除有備註之交易(多為親友交易、價格不正常之交易)
df = df[df['備註'].isnull()]

# 將index改成年月日
df.index = pd.to_datetime((df['交易年月日'].str[:-4].astype(int) + 1911).astype(str) + df['交易年月日'].str[-4:] ,errors='coerce')

接下來我們可以來看一下這些資料有哪些欄位:

1
df.columns

上圖我們比較在意的是:

  • 單價元坪:每坪房價是多少
  • 物件型態:住宅大樓, 倉庫, 公寓, 套房…等
  • 鄉鎮市區:中山區, 中正區, 信義區, 內湖區…等
  • 每年房價的變化

接下來我們就來將上述這些數據,變化成一些圖表,
方便我們以視覺化的方式來理解資料

圖表分析

老實說,每個建商給的房價走勢圖好像都不太一樣,
我不知道他們是怎麼處理這些數據,有時候走勢都好棒棒的感覺
至少finlab的處理的方式,是完全透明,攤在陽光下讓大家知道
我覺得「公佈程式」就是一種比較公正、透明、公開的方式
讓大家檢驗這樣的計算是否公正,
假如哪裡可以再改進,也可以跟我說!

每年房價走勢圖

下圖我們就來計算歷年房價的走勢圖,我們希望每一區可以分開畫
方便我們瞭解地區時間這兩個因子對於房價的差異

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

prices = {}
for district in set(df['鄉鎮市區']):
cond = (
(df['主要用途'] == '住家用')
& (df['鄉鎮市區'] == district)
& (df['單價元坪'] < df["單價元坪"].quantile(0.95))
& (df['單價元坪'] > df["單價元坪"].quantile(0.05))
)

groups = df[cond]['year']

prices[district] = df[cond]['單價元坪'].astype(float).groupby(groups).mean().loc[2012:]

price_history = pd.DataFrame(prices)
price_history.plot()

上圖中我們可以看出來,雖然房價會隨著時間波動,但地段的優勢還是非常的明顯,
例如大安區還是很可怕的,一坪最高可以到90萬元(平均後的數字)
然而以2019年來說,可以發現,

高價位地段 -> 稍微下跌
低價位地段 -> 稍微上漲

畢竟台北的大眾交通工具也算是還OK,住哪裡應該都不至於太不方便
所以在幾乎沒有炒作空間的狀況下,不同地區的差異性慢慢降低,感覺是合理的

那總體來說呢?

我們可以粗略的用簡單的「平均」的方式,將所有地區的房價平均起來:

1
price_history.mean(axis=1).plot()

就會看到2014年高峰後,台北市房價就處於下跌的狀態

不是有人說2019年房價回升了嗎?

刪除outlier的方式不同,可以得出不同的結論,
也是有一些實驗中 2019 年平均房價比 2018 年高,
所以目前也有很多人說止跌回升是有可能的

但是

整體的大趨勢來說,從2014年以後開始下跌至今,似乎跌幅沒有像當初這麼重,
甚至有止跌的跡象,但究竟房價有沒有回升,還需要謹慎評估

甚至還有報導說,某些地段回到了2014、2015高點,這都是拿單一區段來當結論,見樹不見林的方式,背後居心自然是眾人皆知。

思考一下,為何現在都在推新建案?有很多節目,專家們都宣導,買公寓(舊房子)比較可能選到有壁癌、排水系統不好、貸款成數較低…等等,鼓吹大家買新建案。

當然他們很有可能是為了消費者著想,這些都是實話,不過也有可能是因為新房子比起公寓,更能賣出好價錢,進而維持房價不衰退,所以接下來我們就來分析一下

建物型態

1
2
3
4
5
6
7
8
9
10
building_type_prices = {}
for building_type in set(df['建物型態2']):
cond = (
(df['主要用途'] == '住家用')
& (df['單價元坪'] < df["單價元坪"].quantile(0.8))
& (df['單價元坪'] > df["單價元坪"].quantile(0.2))
& (df['建物型態2'] == building_type)
)
building_type_prices[building_type] = df[cond]['單價元坪'].groupby(df[cond]['year']).mean().loc[2012:]
pd.DataFrame(building_type_prices)[['公寓', '住宅大樓', '套房', '華廈']].plot()

上圖中我們可以發現,老舊公寓的價格真的會不太理想,比起一般的大樓住宅或是住宅,近年價差越來越明顯,當價差到達一定的程度,買新房不一定比較好,舊房不一定這麼一無是處。

但是以平均來當作指標,其實也不是這麼精確,我們還是用分佈圖用眼睛來感受一下,才是最好瞭解房價的方法:

分佈圖

1
2
3
4
5
6
7
plt.rcParams['font.size'] = 20
for district in set(df['鄉鎮市區']):
dfdistrict = df[df['鄉鎮市區'] == district]
dfdistrict['單價元坪'][dfdistrict['單價元坪'] < 2000000].hist(bins=120, alpha=0.7)

plt.xlim(0, 2000000)
plt.legend(set(df['鄉鎮市區']))

上圖中可以明顯感受到,不同地區房價的差異性,例如最右邊的分佈(大安區),大部分單價都比較貴,同時我們也可以看到一些低的詭譎的房價(每坪0萬?!),當然也有很多高的咋舌的單價,
甚至一坪200萬都有,只能說富人的世界跟我們一般人還是差距很大呀!

我們取平均的時候無法將這些怪房價給濾除,但好在人眼可以
這就是分佈圖的重要性

買房使用 Python 簡單的範例

假如今天我們想在北投買房子,可以將北投的房價單獨拿出來看,並且按照建案型態製作分佈圖

1
2
3
4
5
6
7
dfdistrict = df[(df['鄉鎮市區'] == '北投區') & (df['year'] >= 2018) & (
(df['建物型態2'] == '住宅大樓') | (df['建物型態2'] == '公寓') | (df['建物型態2'] == '套房')
)]
dfdistrict = dfdistrict[dfdistrict['單價元坪'] < 2000000]

dfdistrict['單價元坪'].groupby(dfdistrict['建物型態2']).hist(bins=50, alpha=0.7)
plt.legend(set(dfdistrict['建物型態2']))

這樣我們就可以一眼看出來,究竟公寓跟電梯大樓有什麼不一樣
方便我們在選擇的時候,多一些考慮
讓我們在買房談價格時,可以有更全面的概念!

有時候買房不是為了投資,而是生活所需而不得不,
在這個時代,我們已經無法買的精妙,炒房產呱呱叫,
但至少在面對這種重大抉擇時,
能有多一份數據輔佐,盡量不要「虧太多」,買到與價格相符的好房!

假如希望我們未來可以多多發佈類似的文章,
可以到粉絲團
幫我們按個讚~!

colab線上編寫此範例

文章不錯,影音課程更讚:


或我們按個 鼓勵一下吧!