前言
曾听人说过,中国经济是房地产市场,美国经济是股票市场。中国房地产市场超过400万亿,房地产总值是美国、欧盟、日本总和,但是股市才50万亿,不到美欧日的十分之一。可见房地产对于中国来说地位尤其明显!对于我们很难在一线城市买房的年轻刚需族来说,这确是一个十分头疼的问题。于此,萌生了分析房价并预测的想法(曾经采用R做过尝试,这次将采用python)。
本次将基于北京房价作为测试数据,后期通过爬虫将抓取包括北上广深等城市的数据以供分析。
数据
感谢Qichen Qiu提供链家网2011-2017北京房价数据,感谢Jonathan Bouchet提供的思路。
本次分析基于python3,代码将稍后整理提供于github。
数据特征包含,kaggle上有具体介绍,在此暂不赘述:
url: the url which fetches the data( character )
id: the id of transaction( character )
Lng: and Lat coordinates, using the BD09 protocol. ( numerical )
Cid: community id( numerical )
tradeTime: the time of transaction( character )
DOM: active days on market.( numerical )
followers: the number of people follow the transaction.( numerical )
totalPrice: the total price( numerical )
price: the average price by square( numerical )
square: the square of house( numerical )
livingRoom: the number of living room( character )
drawingRoom: the number of drawing room( character )
kitchen: the number of kitchen( numerical )
bathroom the number of bathroom( character )
floor: the height of the house. I will turn the Chinese characters to English in the next version.( character )
buildingType: including tower( 1 ) , bungalow( 2 ),combination of plate and tower( 3 ), plate( 4 )( numerical )
constructionTime: the time of construction( numerical )
renovationCondition: including other( 1 ), rough( 2 ),Simplicity( 3 ), hardcover( 4 )( numerical )
buildingStructure: including unknow( 1 ), mixed( 2 ), brick and wood( 3 ), brick and concrete( 4 ),steel( 5 ) and steel-concrete composite ( 6 ).( numerical )
ladderRatio: the proportion between number of residents on the same floor and number of elevator of ladder. It describes how many ladders a resident have on average.( numerical )
elevator have ( 1 ) or not have elevator( 0 )( numerical )
fiveYearsProperty: if the owner have the property for less than 5 years( numerical )
EDA
了解数据以后,首先进行探索分析,查看缺失值情况:
url 0
id 0
Lng 0
Lat 0
Cid 0
tradeTime 0
DOM 0
followers 0
totalPrice 0
price 0
square 0
livingRoom 0
drawingRoom 0
kitchen 0
bathRoom 0
floor 0
buildingType 2021
constructionTime 0
renovationCondition 0
buildingStructure 0
ladderRatio 0
elevator 32
fiveYearsProperty 32
subway 32
district 0
communityAverage 463
get_floor 32
province 0
dtype: int64
采用msno图形化查看:
msno.matrix(source_data)
针对不同特征对缺失值进行填补处理:
test_data.fillna({'DOM': test_data['DOM'].median()}, inplace=True)
test_data['buildingType'] = [makeBuildingType(x) for x in test_data['buildingType']]
test_data = test_data[(test_data['buildingType'] != 'wrong_coded') & (test_data['buildingType'] != 'missing')]
test_data['renovationCondition'] = [makeRenovationCondition(x) for x in test_data['renovationCondition']]
test_data['buildingStructure'] = [makeBuildingStructure(x) for x in test_data['buildingStructure']]
test_data['elevator'] = ['has_elevator' if x==1 else 'no_elevator' for x in test_data['elevator']]
test_data['subway'] = ['has_subway' if x==1 else 'no_subway' for x in test_data['subway']]
test_data['fiveYearsProperty'] = ['owner_less_5y' if x==1 else 'owner_more_5y' for x in test_data['fiveYearsProperty']]
pd.to_numeric(test_data['constructionTime'], errors='coerce')
test_data = test_data[(test_data['constructionTime'] != '未知')]
# pd.value_counts(test_data['constructionTime'])
test_data['district'].astype("category")
print(pd.value_counts(test_data['district']))
结果如下:
我们来看一看房价情况:
首先总体情况:
再看一看2017年的情况:
可见房价总体满足正偏分布。
处理下数据看一看相关性:
test_data['tradeTime'] = pd.to_datetime(test_data['tradeTime'])
test_data['constructionTime'] = pd.to_numeric(test_data['constructionTime'])
test_data['livingRoom'] = pd.to_numeric(test_data['livingRoom'])
test_data['drawingRoom'] = pd.to_numeric(test_data['drawingRoom'])
test_data['bathRoom'] = pd.to_numeric(test_data['bathRoom'])
test_data['get_floor'] = pd.to_numeric(test_data['get_floor'])
抽部分特征看一看:
communityAverage:
square:
再看看电梯和区域:
房价真的是没有最高只有更高!一般情况下,尽量分区域进行分析会更直观也更准确。比如海淀和通州就会差别较大。
包括卧室,浴室等特征基本上都与总价成正相关,不过还有单价或总价为0的需要考虑是缺失还是已售/待定等情况,这些在自己抓取房价的时候要注意分析。
最后看一下均价和计数:
price_data = test_data[['price','year-month']]
price_data.head()
price_group = price_data.groupby(['year-month']).agg(['mean','count'])
price_group.head()
2017年中旬出现拐点,点的大小代表该价格计数。
到这里已经很想加上2018年的数据看看了!
回归
试试多元线性回归:
用2017年以前的数据进行训练,预测2017的价格。
训练模型:
x_train = temp_train.drop(['tradeTime','totalPrice','floor','province'], axis=1)
y_train = temp_train[['totalPrice']]
model = LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=1)
model.fit(x_train,y_train)
x_test = temp_test.drop(['tradeTime','totalPrice','floor','province'], axis=1)
y_test = temp_test[['totalPrice']]
print(model.score(x_test,y_test))
第一次拟合优度0.7971355163827527.
预测值普遍偏低。
后期将用更多的特征组合以及参数来进行尝试,并采用不同的方式进行预测。