用程式分析房地產可行嗎?房價分析看這裡!

fb11 1

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

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

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

難道數據造假?!

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

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

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

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

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

取得實價登錄資料

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

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 我們可以將實價登錄資訊全部爬取下來:

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」,以此類推。

讀取資料

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

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)
dfhead 1

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

# 新增交易年份
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')

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

df.columns
dfcolumn

上圖我們比較在意的是:

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

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

圖表分析

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

每年房價走勢圖

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


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()
dts

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

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

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

那總體來說呢?

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

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

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

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

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

但是

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

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

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

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

建物型態

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()
tts

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

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

分佈圖

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['鄉鎮市區']))
dhis

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

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

買房使用 Python 簡單的範例

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

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']))
bhis

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

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

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

FinLab - 韓承佑

嗨大家好,我是韓承佑,FinLab創辦人,畢業於巴黎薩克雷大學資工博士,目前擔任臺灣量化交易協會 學術顧問、台北商業大學 創新育成中心 創業技術顧問與上市科技公司 量化交易顧問。當初,我喜歡寫程式、無意間因為軟體比賽接觸Fintech,從此開始了財經跟程式的學習之路。我們成立 FinLab 量化投資部落格,用自己研發的軟體,對台灣股市做大量快速的實驗。希望可以在量化投資的路上,當大家的「武器製造商」!