包含全部示例的代码仓库见GIthub
1 导入库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn import metrics
2 数据准备
data_list = []
for i in range(1,8):
try:
data = pd.read_csv('./dataset/lianjia{}.csv'.format(i), encoding='gbk')
except:
data = pd.read_csv('./dataset/lianjia{}.csv'.format(i))
finally:
data_list.append(data)
data = pd.concat(data_list)
data = data.dropna()
data = data[data.cjshijian.str.contains('2015-')]
data.head()
# output
cjtaoshu mendian cjzongjia zhiwei haoping cjdanjia cjxiaoqu xingming cjzhouqi biaoqian cjlouceng cjshijian congyenianxian bankuai
0 37 红莲北里店 251.0 店经理 97% 141 43997元/平 红莲北里 3室1厅 57平 郭海龙 36 房东信赖;销售达人;带看活跃 南 北/高楼层/6层 签约时间:2015-05-24 4-5年 马连道
1 37 红莲北里店 159.0 店经理 97% 141 36969元/平 红莲南里 1室1厅 43平 郭海龙 36 房东信赖;销售达人;带看活跃 南/高楼层/7层 签约时间:2015-05-10 4-5年 马连道
2 37 红莲北里店 257.0 店经理 97% 141 39046元/平 常青藤嘉园 1室1厅 65平 郭海龙 36 房东信赖;销售达人;带看活跃 北/低楼层/16层 签约时间:2015-04-26 4-5年 马连道
3 37 红莲北里店 243.0 店经理 97% 141 41313元/平 红莲北里 2室1厅 58平 郭海龙 36 房东信赖;销售达人;带看活跃 南 北/高楼层/6层 签约时间:2015-04-04 4-5年 马连道
4 37 红莲北里店 372.5 店经理 97% 141 42053元/平 广安门外大街 3室1厅 88平 郭海龙 36 房东信赖;销售达人;带看活跃 东 南 西 北/中楼层/18层 签约时间:2015-04-01 4-5年 马连道
data = data[['cjdanjia', 'cjxiaoqu', 'cjlouceng']]
data
# output
cjdanjia cjxiaoqu cjlouceng
0 43997元/平 红莲北里 3室1厅 57平 南 北/高楼层/6层
1 36969元/平 红莲南里 1室1厅 43平 南/高楼层/7层
2 39046元/平 常青藤嘉园 1室1厅 65平 北/低楼层/16层
3 41313元/平 红莲北里 2室1厅 58平 南 北/高楼层/6层
4 42053元/平 广安门外大街 3室1厅 88平 东 南 西 北/中楼层/18层
... ... ... ...
6591 27835元/平 富力又一城C区 2室2厅 88平 南/高楼层/23层
6592 20820元/平 扬州水乡 3室1厅 122平 南 北/中楼层/5层
6593 20302元/平 扬州水乡 2室2厅 76平 南 北/低楼层/3层
6594 26948元/平 富力又一城A区 3室2厅 139平 南 北/中楼层/22层
6659 11829元/平 福城上上城三季 2室1厅 59平 北/中楼层/26层
data.cjdanjia = np.round(data.cjdanjia.str.replace('元/平','').astype(np.float32).map(lambda x:x/10000),2)
data.head()
# output
cjdanjia cjxiaoqu cjlouceng
0 4.40 红莲北里 3室1厅 57平 南 北/高楼层/6层
1 3.70 红莲南里 1室1厅 43平 南/高楼层/7层
2 3.90 常青藤嘉园 1室1厅 65平 北/低楼层/16层
3 4.13 红莲北里 2室1厅 58平 南 北/高楼层/6层
4 4.21 广安门外大街 3室1厅 88平 东 南 西 北/中楼层/18层
删除异常数据
(data.cjxiaoqu.str.split().map(len) != 3).sum()
# output
3
data = data[data.cjxiaoqu.str.split().map(len) == 3]
data = data.assign(xiaoqu = data.cjxiaoqu.map(lambda x:x.split()[0]))
data = data.assign(huxing = data.cjxiaoqu.map(lambda x:x.split()[1]))
data = data.assign(mianji = data.cjxiaoqu.map(lambda x:x.split()[2]))
del data['cjxiaoqu']
data
# output
cjdanjia cjlouceng xiaoqu huxing mianji
0 4.40 南 北/高楼层/6层 红莲北里 3室1厅 57平
1 3.70 南/高楼层/7层 红莲南里 1室1厅 43平
2 3.90 北/低楼层/16层 常青藤嘉园 1室1厅 65平
3 4.13 南 北/高楼层/6层 红莲北里 2室1厅 58平
4 4.21 东 南 西 北/中楼层/18层 广安门外大街 3室1厅 88平
... ... ... ... ... ...
6591 2.78 南/高楼层/23层 富力又一城C区 2室2厅 88平
6592 2.08 南 北/中楼层/5层 扬州水乡 3室1厅 122平
6593 2.03 南 北/低楼层/3层 扬州水乡 2室2厅 76平
6594 2.69 南 北/中楼层/22层 富力又一城A区 3室2厅 139平
6659 1.18 北/中楼层/26层 福城上上城三季 2室1厅 59平
查看是否还有异常值
data[data.cjlouceng.str.split('/').map(len) != 3]
# output
cjdanjia cjlouceng xiaoqu huxing mianji
data = data.assign(chaoxiang = data.cjlouceng.map(lambda x:x.split('/')[0]))
data = data.assign(louceng = data.cjlouceng.map(lambda x:x.split('/')[1]))
del data['cjlouceng']
data
# output
cjdanjia xiaoqu huxing mianji chaoxiang louceng
0 4.40 红莲北里 3室1厅 57平 南 北 高楼层
1 3.70 红莲南里 1室1厅 43平 南 高楼层
2 3.90 常青藤嘉园 1室1厅 65平 北 低楼层
3 4.13 红莲北里 2室1厅 58平 南 北 高楼层
4 4.21 广安门外大街 3室1厅 88平 东 南 西 北 中楼层
... ... ... ... ... ... ...
6591 2.78 富力又一城C区 2室2厅 88平 南 高楼层
6592 2.08 扬州水乡 3室1厅 122平 南 北 中楼层
6593 2.03 扬州水乡 2室2厅 76平 南 北 低楼层
6594 2.69 富力又一城A区 3室2厅 139平 南 北 中楼层
6659 1.18 福城上上城三季 2室1厅 59平 北 中楼层
取出成交量前十五的小区的成交数据
top15 = data.xiaoqu.value_counts()[:15].index
data = data[data.xiaoqu.isin(top15)] # 取出成交量前十五的小区的成交数据
data
# output
cjdanjia xiaoqu huxing mianji chaoxiang louceng
31 6.62 荣丰2008 1室1厅 32平 南 低楼层
347 3.97 远洋山水 1室--厅 56平 东 中楼层
388 3.01 北京像素北区 2室1厅 57平 西南 低楼层
716 2.90 北京像素北区 2室1厅 58平 东北 中楼层
260 3.81 沿海赛洛城 1室1厅 64平 东 低楼层
... ... ... ... ... ... ...
3769 2.07 天通苑东一区 2室1厅 96平 东 低楼层
4096 2.96 芍药居北里 1室1厅 56平 南 低楼层
4230 1.93 天通苑东一区 3室2厅 130平 南 北 中楼层
4232 2.50 天通苑东一区 2室1厅 76平 南 北 中楼层
5379 1.94 天通苑东一区 2室1厅 101平 东 南 高楼层
产出'平'
data.mianji = data.mianji.str.replace('平','').astype(np.float32)
data.head()
# output
cjdanjia xiaoqu huxing mianji chaoxiang louceng
31 6.62 荣丰2008 1室1厅 32.0 南 低楼层
347 3.97 远洋山水 1室--厅 56.0 东 中楼层
388 3.01 北京像素北区 2室1厅 57.0 西南 低楼层
716 2.90 北京像素北区 2室1厅 58.0 东北 中楼层
260 3.81 沿海赛洛城 1室1厅 64.0 东 低楼层
异常值处理
data.xiaoqu.unique()
# output
array(['荣丰2008', '远洋山水', '北京像素北区', '沿海赛洛城', '东亚上北中心', '天通西苑二区', '芍药居北里',
'北京新天地', '北京像素南区', '新龙城', '青年汇佳园', '天通苑中苑', '天通苑东一区', '海特花园小区',
'天通西苑三区'], dtype=object)
data.chaoxiang.unique()
# output
array(['南', '东', '西南', '东北', '南 北', '西 南', '东 南', '东 南 北', '西北', '东 北',
'东 西', '西', '北', '西 北', '东南', '南 西', '东 南 西', '西 南 北', '南 北 西',
'东 西 北', '南 西 北', '西南 东北', '南 北 东', '暂无数据', '北 东南', '北 西南',
'东 西 南', '东 北 南'], dtype=object)
data = data[data.chaoxiang != '暂无数据']
data.chaoxiang.unique()
# output
array(['南', '东', '西南', '东北', '南 北', '西 南', '东 南', '东 南 北', '西北', '东 北',
'东 西', '西', '北', '西 北', '东南', '南 西', '东 南 西', '西 南 北', '南 北 西',
'东 西 北', '南 西 北', '西南 东北', '南 北 东', '北 东南', '北 西南', '东 西 南',
'东 北 南'], dtype=object)
data.louceng.unique()
# output
array(['低楼层', '中楼层', '高楼层', '地下室'], dtype=object)
data.huxing.unique()
# output
array(['1室1厅', '1室--厅', '2室1厅', '2室2厅', '3室2厅', '4室2厅', '1室2厅', '3室1厅',
'5室1厅', '3室--厅', '5室--厅', '4室1厅', '5室2厅', '3室3厅', '2室--厅', '2室3厅',
'4室--厅'], dtype=object)
data = data.join(pd.get_dummies(data[['xiaoqu','huxing','louceng']]))
data
# output
cjdanjia xiaoqu huxing mianji chaoxiang louceng xiaoqu_东亚上北中心 xiaoqu_北京像素北区 xiaoqu_北京像素南区 xiaoqu_北京新天地 ... huxing_4室--厅 huxing_4室1厅 huxing_4室2厅 huxing_5室--厅 huxing_5室1厅 huxing_5室2厅 louceng_中楼层 louceng_低楼层 louceng_地下室 louceng_高楼层
31 6.62 荣丰2008 1室1厅 32.0 南 低楼层 0 0 0 0 ... 0 0 0 0 0 0 0 1 0 0
148 3.86 芍药居北里 1室1厅 43.0 南 地下室 0 0 0 0 ... 0 0 0 0 0 0 0 0 1 0
260 3.81 沿海赛洛城 1室1厅 64.0 东 低楼层 0 0 0 0 ... 0 0 0 0 0 0 0 1 0 0
261 3.32 沿海赛洛城 1室1厅 57.0 东 中楼层 0 0 0 0 ... 0 0 0 0 0 0 1 0 0 0
285 3.96 沿海赛洛城 2室2厅 105.0 南 北 中楼层 0 0 0 0 ... 0 0 0 0 0 0 1 0 0 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
56956 3.59 新龙城 1室1厅 56.0 北 低楼层 0 0 0 0 ... 0 0 0 0 0 0 0 1 0 0
56957 2.20 天通苑东一区 2室1厅 94.0 东南 中楼层 0 0 0 0 ... 0 0 0 0 0 0 1 0 0 0
56960 3.11 新龙城 1室2厅 70.0 南 低楼层 0 0 0 0 ... 0 0 0 0 0 0 0 1 0 0
56961 3.18 新龙城 3室2厅 111.0 南 北 高楼层 0 0 0 0 ... 0 0 0 0 0 0 0 0 0 1
56962 2.83 新龙城 2室2厅 98.0 东 西 中楼层 0 0 0 0 ... 0 0 0 0 0 0 1 0 0 0
1852 rows × 42 columns
对chaoxiang
进行独热编码
len(data.chaoxiang.unique())
# output
27
data.chaoxiang.unique()
# output
array(['南', '东', '南 北', '东 西', '南 西', '南 北 西', '西南', '西 北', '东南', '东 北',
'东 南', '西 南', '东北', '东 南 北', '西北', '西', '北', '西南 东北', '西 南 北',
'东 南 西', '南 北 东', '南 西 北', '东 西 北', '东 西 南', '北 东南', '北 西南',
'东 北 南'], dtype=object)
data['dong'] = (data.chaoxiang.map(lambda x:'东' in x.split())).astype(np.int32)
data['xi'] = (data.chaoxiang.map(lambda x:'西' in x.split())).astype(np.int32)
data['nan'] = (data.chaoxiang.map(lambda x:'南' in x.split())).astype(np.int32)
data['bei'] = (data.chaoxiang.map(lambda x:'北' in x.split())).astype(np.int32)
data['dongnan'] = (data.chaoxiang.map(lambda x:'东南' in x.split() or '南东' in x.split())).astype(np.int32)
data['dongbei'] = (data.chaoxiang.map(lambda x:'东北' in x.split())).astype(np.int32)
data['xinan'] = (data.chaoxiang.map(lambda x:'西南' in x.split())).astype(np.int32)
data['xibei'] = (data.chaoxiang.map(lambda x:'西北' in x.split())).astype(np.int32)
data.drop(data.columns[[1,2,4,5]], axis=1, inplace=True) # 删除多列
data
# output
cjdanjia mianji xiaoqu_东亚上北中心 xiaoqu_北京像素北区 xiaoqu_北京像素南区 xiaoqu_北京新天地 xiaoqu_天通苑东一区 xiaoqu_天通苑中苑 xiaoqu_天通西苑三区 xiaoqu_天通西苑二区 ... louceng_地下室 louceng_高楼层 dong xi nan bei dongnan dongbei xinan xibei
31 6.62 32.0 0 0 0 0 0 0 0 0 ... 0 0 0 0 1 0 0 0 0 0
148 3.86 43.0 0 0 0 0 0 0 0 0 ... 1 0 0 0 1 0 0 0 0 0
260 3.81 64.0 0 0 0 0 0 0 0 0 ... 0 0 1 0 0 0 0 0 0 0
261 3.32 57.0 0 0 0 0 0 0 0 0 ... 0 0 1 0 0 0 0 0 0 0
285 3.96 105.0 0 0 0 0 0 0 0 0 ... 0 0 0 0 1 1 0 0 0 0
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
56956 3.59 56.0 0 0 0 0 0 0 0 0 ... 0 0 0 0 0 1 0 0 0 0
56957 2.20 94.0 0 0 0 0 1 0 0 0 ... 0 0 0 0 0 0 1 0 0 0
56960 3.11 70.0 0 0 0 0 0 0 0 0 ... 0 0 0 0 1 0 0 0 0 0
56961 3.18 111.0 0 0 0 0 0 0 0 0 ... 0 1 0 0 1 1 0 0 0 0
56962 2.83 98.0 0 0 0 0 0 0 0 0 ... 0 0 1 1 0 0 0 0 0 0
Y = data.cjdanjia
X = data[[x for x in data.columns if x != 'cjdanjia']]
X_train, X_test, Y_train, Y_test = train_test_split(X, Y)
X_train.shape, np.shape(X_train), np.shape(X_train.values)
# output
((1389, 45), (1389, 45), (1389, 45))
3 模型构建
model = LinearRegression()
model.fit(X_train, Y_train)
4 模型评价
metrics.mean_squared_error(model.predict(X_test), Y_test)
# output
0.3120292004271854
5 模型预测
data_test = pd.Series(np.zeros(len([x for x in data.columns if x != 'cjdanjia'])),
index = [x for x in data.columns if x != 'cjdanjia'])
data_test.mianji = 80
data_test.xiaoqu_天通西苑三区 = 1
data_test.nan = 1
data_test.bei = 1
data_test.huxing_2室2厅 = 1
data_test.louceng_高楼层 = 1
data_test
# output
mianji 80.0
xiaoqu_东亚上北中心 0.0
xiaoqu_北京像素北区 0.0
xiaoqu_北京像素南区 0.0
xiaoqu_北京新天地 0.0
xiaoqu_天通苑东一区 0.0
xiaoqu_天通苑中苑 0.0
xiaoqu_天通西苑三区 1.0
xiaoqu_天通西苑二区 0.0
xiaoqu_新龙城 0.0
xiaoqu_沿海赛洛城 0.0
xiaoqu_海特花园小区 0.0
xiaoqu_芍药居北里 0.0
xiaoqu_荣丰2008 0.0
xiaoqu_远洋山水 0.0
xiaoqu_青年汇佳园 0.0
huxing_1室--厅 0.0
huxing_1室1厅 0.0
huxing_1室2厅 0.0
huxing_2室--厅 0.0
huxing_2室1厅 0.0
huxing_2室2厅 1.0
huxing_2室3厅 0.0
huxing_3室--厅 0.0
huxing_3室1厅 0.0
huxing_3室2厅 0.0
huxing_3室3厅 0.0
huxing_4室--厅 0.0
huxing_4室1厅 0.0
huxing_4室2厅 0.0
huxing_5室--厅 0.0
huxing_5室1厅 0.0
huxing_5室2厅 0.0
louceng_中楼层 1.0
louceng_低楼层 0.0
louceng_地下室 0.0
louceng_高楼层 1.0
dong 0.0
xi 0.0
nan 1.0
bei 1.0
dongnan 0.0
dongbei 0.0
xinan 0.0
xibei 0.0
model.predict(data_test.values.reshape(1,-1))
# output
array([3.25528068])