大鵬說:本文約1500字,閱讀需要5分鐘。講述了如何使用python進行房價信息獲取,如何利用R構建回歸模型以達到預測上海某個地區房價的目的。
關鍵詞:買房 Python 選房 R 定價
本文講述了借助Python,Gis和R語言制作房源定價系統的方法,對原理、過程都有詳細的講述
p.s.文末有源代碼分享
為了能在當今競爭激烈的社會活下去,我一直在孜孜不倦地開發自己的潛能,尋找更多的副職業增加收入,從而在雙十一后的雙十二可以繼續剁手。
這不,成為業余房地產咨詢師的第一天,客戶戳我了:我要在上海16個區買16套房子,資金到位,您給估個價吧。
對于這類在在如此嚴峻的房地產政策之下,還想擁有兩位數以上房產的“忽悠”高手,我一向給予至尊VIP的待遇。
決定一套房子價格的因素主要是三個方面,房屋本身的屬性,房屋的空間位置和周邊的其他因素。這篇文章會講述考慮這些因素的分析——建模——檢驗的過程。
1、 數據集的準備
這里分為兩步:
第一步,抓取所有URL:
if__name__=='__main__':
url_list = create_url(220,2)#填寫區間最大面積和公差,保證按大于最大面積搜索,房源數小于等于3000
data_list = []
#data_list = craw_second_url(url_list)
craw_second_url(url_list)
data = pd.DataFrame(pd.Series(data_list),columns=['url'])
data.to_csv('./urls.csv',encoding='gbk',index=0)
print('finish')
第二步,爬取房源信息:
defread_url(path):
path = path
data = pd.read_csv(path,engine='python')
try:
data_received = pd.read_csv('./house_inf_lianjia.csv',engine='python')
print('導入爬取數據')
data_received_list = data_received['url'].tolist()
print('轉換表格')
url_list = data[~data['url'].isin(data_received_list)]['url'].unique().tolist()
print('剔除已爬取數據')
print(len(url_list))
except:
url_list = data['url'].unique().tolist()
data = pd.DataFrame(
columns=['house_id','name','price','area_price','area','room','livingroom','kitchenroom',
'bathroom','lng','lat','url'])
data.to_csv('./house_inf_lianjia.csv', encoding='gbk', index=0)
print('無歷史數據')
returnurl_list
我還順手做了一個斷點續傳功能,每次開始爬蟲前會匹配URL列表,保證爬取過的不再爬取,方便更新和分時段爬取。詳細代碼請見文末,我爬取了1W+的數據作為樣本:
另外,我準備了另一份數據:美團美食頻道1W+的餐飲POI. 同樣使用爬蟲獲取。
2、建模準備
這一部分我們會將房源數據和POI數據等信息整合在一起用于建模,可以用ArcGis完成。紅色的為餐飲POI,綠色的為房源數據(有時間的朋友可以爬取全量數據)。如果你不知道ArcGIS是什么,你可以理解為一個處理地理數據的軟件,一般來說熟悉python庫的人也可以使用geopandas進行處理,但前提是要求你對地理數據有一定的理解。這里我推薦下我以前講過的“大鵬教你玩數據”幫助你了解數據類型,點擊進入第一章“arcgis深入解讀”
先對房源做緩沖區,緩沖區半徑為1KM,計算出落點在這個范圍內的POI數據。
結果如圖:
然后使用緩沖區與餐飲POI進行空間關聯,這樣就可以統計出一個房源1KM半徑范圍內餐飲POI的數量,價格,評論數等等信息,以便接下來建模使用。
另外,常識告訴我們,一般離市中心越近,房價越高,隨意我們再增加一個距離屬性。先添個底圖:
然后創建一個上海中心點點數據。上海的中心點,在人民廣場附近,方便起見,就在地圖上點一個吧!
把圖層轉換成投影坐標系,便于計算距離:
給中心點數據和緩沖區數據添加兩個字段,存放投影經緯度
然后使用計算幾何,獲取投影經緯度,單位選擇米
結果如圖(部分):
接下來計算距離,可以在GIS內直接操作,也可以導出數據,在EXCEL中用兩點之間距離公式計算。
這樣,我們就整合完成了一份樣本數據,可以用來進行建模操作!
3、建模操作
左手python右手R,先導入一堆包:
library(readr)
library(funr)
library(openxlsx)
library(dplyr)
library(caret)
library(readxl)
library(psych)
library(plyr)
library(ggplot2)
創建工作路徑和讀取數據
########################################### path setting and data reading ##########################################
path <- get_script_path()# 獲取腳本路徑
# path = '' #可以手動輸入工作路徑
print(path)
setwd(path)# 設定工作路徑
model_data <- read_csv("model_data.csv")
然后,是數據清洗,提煉我們需要建模的屬性
########################################### Data cleaning ##########################################
model_data <- na.omit(model_data)
model_data <- model_data %>% select(price,area,room,livingroom,kitchenroom,
bathroom,Count_,Sum_allcommentNum,Avg_allcommentNum,
Avg_avgprice,Avg_avgscore,Sum_avgscore,len)#可以使用names(model_data)函數在Console中查看字段名稱
model_data <- rename(model_data,c(Count_='resturant_counts'))
我們今天要擬合一個回歸模型,所以,先來看一看屬性之間的相關性
psych::pairs.panels(model_data)#查看相關性
這行代碼會畫出一張逼格很高的圖:
理解幾個關鍵點:
1.相關性系數,絕對值越接近1表明相關性越顯著,比如房價和面積相關度為0.77;
2.圖中的直方圖為每個維度的數據分布;
3.散點圖中圓越完美表明相關度越低,橢圓形狀表明相關度顯著。
4.圖中的線條是查看線性關系的,可以體現自變量和因變量之間的關系。
下面,我們使用全部屬性構建一個回歸模型。Price是因變量,“~.”表示導入所有自變量。最后打印模型結果查看。
model <-lm(price~.,data=model_data)
print(summary(model))
print(car::vif(model))
我們可以從結果中讀取到擬合后的函數,殘差,回歸系數,P值,R方等。對于多元線性回歸,R方會隨著變量的增多不變或增加,所以看實際R方并不科學,模型引入了懲罰因子,最后,我們以調整R方作為最終判定擬合度的依據。我們看到,R方為0.8393,擬合度應該相當不錯。
然后,我們還要關注一下共線問題。
什么是共線問題?
簡單說就是兩個變量描述的是同一個內容,我們需要去掉其中一個。比如,“雙十一我剁手了”和”我這個月要吃土了”表達的是一個意思:沒錢!
我們看到緩沖區內餐廳數量和平均得分之和數字都超過了200,只要大于10的都屬于共線,應該根據具體情況刪減。
下面我們使用逐步回歸法,優化模型。
逐步回歸分三種,這里我直接百度介紹:
model_step <- step(model,direction ="both")# 使用逐步回歸的方法篩選變量
print(summary(model_step))
優化后的模型為:
我們看到,R方進一步提升,達到0.8415。不過,有一個問題,這里去掉了餐廳數量,選擇使用評分總和作為其中一個變量,但這里根據我們經驗,常識和習慣,這樣并不科學。
所以,我們人工替換回餐廳數量這個變量再一次擬合。
model_fin <- lm(formula = price ~ area + room + bathroom + Sum_allcommentNum +
Avg_allcommentNum + Avg_avgprice + resturant_counts + len, data = model_data)
擬合結果:
R方下降0.0001,幾乎沒有變化,完美!
我們導出回歸模型,方便查看。
table = data.frame(summary(model_fin)[["coefficients"]])
table['variable']=row.names(table)
write.xlsx(x = table,file ='coefficients.xlsx',
sheetName ='sheet1',
row.names =FALSE,
overwrite=TRUE)
Estimate為回歸系數,std.error為標準誤差,t.value為t值,pr.t為P值,顯然所有變量P值均小于0.05,非常顯著。
最后,我們來使用這個模型,來給房源定價:
predict_result <- predict(model_fin,
data.frame(area =108,
room=3,
bathroom=2,
Sum_allcommentNum=56399,
Avg_allcommentNum=247.36,
Avg_avgprice=114.12,
resturant_counts=228,
len=6438),
interval ='confidence')
print(predict_result)
用法很簡單,輸入房源的信息,就能預測出結果。比如108平米,3房2衛,1KM半徑緩沖區內有228家餐廳,平均價格114.2,平均評論數247.36,評論綜合56399條,距離市中心6.438KM,最終結果如下:
(從左往右分別是:估價-最低估價-最高估價)
嘖嘖~按月薪1W計算,一年12W,需要工作
客戶看了我的定價模型以后,面帶笑容,似乎感覺非常滿意!
突然他問我道:在上海郊環以外,有沒有10平米的合租房?
如需獲得文中數據、完整代碼以請關注公號“大鵬教你玩數據”,并在后臺回復【22】
與大鵬交流,請加數據團學社群290745151