包含全部示例的代码仓库见GIthub
1 导入库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
from sklearn.linear_model import LogisticRegression
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[['cjzongjia','cjdanjia','cjxiaoqu','cjlouceng','cjshijian',
'bankuai','mendian','xingming','congyenianxian']]
data.cjdanjia = np.round(data.cjdanjia.str.replace('元/平','').astype(np.float32).map(lambda x:x/10000),2)
data.head()
# output
cjzongjia cjdanjia cjxiaoqu cjlouceng cjshijian bankuai mendian xingming congyenianxian
0 251.0 4.40 红莲北里 3室1厅 57平 南 北/高楼层/6层 签约时间:2015-05-24 马连道 红莲北里店 郭海龙 4-5年
1 159.0 3.70 红莲南里 1室1厅 43平 南/高楼层/7层 签约时间:2015-05-10 马连道 红莲北里店 郭海龙 4-5年
2 257.0 3.90 常青藤嘉园 1室1厅 65平 北/低楼层/16层 签约时间:2015-04-26 马连道 红莲北里店 郭海龙 4-5年
3 243.0 4.13 红莲北里 2室1厅 58平 南 北/高楼层/6层 签约时间:2015-04-04 马连道 红莲北里店 郭海龙 4-5年
4 372.5 4.21 广安门外大街 3室1厅 88平 东 南 西 北/中楼层/18层 签约时间:2015-04-01 马连道 红莲北里店 郭海龙 4-5年
异常值处理
data = data[data.cjshijian.map(lambda x:isinstance(x, str))]
# isinstance(x, str) 判断x是否为str类型
data.cjshijian = pd.to_datetime(data.cjshijian.str.replace('签约时间:',''))
data
# output
cjzongjia cjdanjia cjxiaoqu cjlouceng cjshijian bankuai mendian xingming congyenianxian
0 251.00 4.40 红莲北里 3室1厅 57平 南 北/高楼层/6层 2015-05-24 马连道 红莲北里店 郭海龙 4-5年
1 159.00 3.70 红莲南里 1室1厅 43平 南/高楼层/7层 2015-05-10 马连道 红莲北里店 郭海龙 4-5年
2 257.00 3.90 常青藤嘉园 1室1厅 65平 北/低楼层/16层 2015-04-26 马连道 红莲北里店 郭海龙 4-5年
3 243.00 4.13 红莲北里 2室1厅 58平 南 北/高楼层/6层 2015-04-04 马连道 红莲北里店 郭海龙 4-5年
4 372.50 4.21 广安门外大街 3室1厅 88平 东 南 西 北/中楼层/18层 2015-04-01 马连道 红莲北里店 郭海龙 4-5年
... ... ... ... ... ... ... ... ... ...
6653 145.00 2.28 天洋城 1室1厅 63平 西/高楼层/31层 2016-07-13 燕郊城区 天洋城一店 倪海新 <1年
6656 390.00 8.10 平原里小区 1室--厅 48平 东 西/中楼层/9层 2016-09-11 白纸坊 半步桥小学店 蒲宁宁 <1年
6657 100.00 1.91 美林湾 1室1厅 52平 西/高楼层/34层 2016-04-10 燕郊城区 国道总部店 衣健华 1-2年
6658 71.75 1.21 燕郊电子城小区 2室1厅 59平 南 北/高楼层/6层 2016-01-29 燕郊城区 国道总部店 衣健华 1-2年
6659 70.00 1.18 福城上上城三季 2室1厅 59平 北/中楼层/26层 2015-12-20 燕郊城区 国道总部店 衣健华 1-2年
data = data.set_index('cjshijian')
data = data.sort_index() # 索引排序
data3 = data['2015-01-01':'2015-9-30'] # 选取2015年数据前3季度数据,pandas索引切片前后都包含
data4 = data['2015-10-01':'2015-12-31']
选择成交数量大于5的小区
data3 = data3.assign(xiaoqu = data3.cjxiaoqu.map(lambda x:x.split()[0]))
all6 = data3.xiaoqu.value_counts()[data3.xiaoqu.value_counts() > 5].index
data3 = data3[data3.xiaoqu.isin(all6)]
data3_m = data3.groupby('xiaoqu').cjdanjia.mean()
data4 = data4.assign(xiaoqu = data4.cjxiaoqu.map(lambda x:x.split()[0]))
data4 = data4[data4.xiaoqu.isin(all6)]
data4_m = data4.groupby('xiaoqu').cjdanjia.mean()
第四季度涨幅比例
xq_up = (data4_m - data3_m)/data3_m # 涨幅比例
拼接特征涨幅,套数到dataframe
(xq_up > 0.1).sum()
# output
545
len(xq_up)
# output
1591
xq_up = xq_up.dropna()
type(xq_up)
# output
pandas.core.series.Series
xq_up = xq_up.to_frame() # Series 转 dataframe
xq_up = xq_up.assign(zhangfu = (xq_up.cjdanjia > 0.1).astype('int')) # 涨幅大于0.1的转为1
data_taoshu = data3.groupby('xiaoqu').count()['cjxiaoqu'].to_frame().rename(columns={'cjxiaoqu':'taoshu'})
data = pd.merge(xq_up, data_taoshu, left_index=True, right_index=True, how='left') # 以左边的xq_up为准合并
del data['cjdanjia']
拼接特征成交单价,成交总价到dataframe
data_danjia = data3.groupby('xiaoqu').cjdanjia.mean().to_frame()
data = pd.merge(data, data_danjia, left_index=True, right_index=True, how='left')
data_zongjia = data3.groupby('xiaoqu').cjzongjia.mean().to_frame()
data = pd.merge(data, data_zongjia, left_index=True, right_index=True, how='left')
data
# output
zhangfu taoshu cjdanjia cjzongjia
xiaoqu
10AM新坐标 0 16 3.359375 181.412500
11站 1 8 2.366250 180.950000
7克拉 0 13 3.601538 130.538462
@北京 1 6 1.238333 79.083333
BOBO自由城 1 27 2.565556 247.024444
... ... ... ... ...
龙锦苑东四区 0 16 2.041875 230.112500
龙锦苑二区 1 9 2.715556 280.722222
龙锦苑六区 0 14 2.880714 277.985714
龙锦苑四区 0 11 2.930909 289.272727
龙鼎园 1 20 1.990000 186.905000
3 模型构建
index = np.random.permutation(len(data)) # 乱序
data_train = data.iloc[index[:int(0.7*len(data))]] # 对index切片
data_test = data.iloc[index[int(0.7*len(data))]:] # iloc切片
x_train, y_train = data_train[['taoshu', 'cjdanjia', 'cjzongjia']], data_train.zhangfu
x_test, y_test = data_test[['taoshu', 'cjdanjia', 'cjzongjia']], data_test.zhangfu
model = LogisticRegression()
model.fit(x_train, y_train)
model.score(x_test, y_test)
# output
0.6428571428571429
4 模型改进 增加特征
data_jjr_num = data3.groupby('xiaoqu').xingming.unique().map(len).to_frame()
data = pd.merge(data, data_jjr_num, left_index=True, right_index=True, how='left')
data_md_num = data3.groupby('xiaoqu').mendian.unique().map(len).to_frame()
data = pd.merge(data, data_md_num, left_index=True, right_index=True, how='left')
data
# output
zhangfu taoshu cjdanjia cjzongjia xingming mendian
xiaoqu
10AM新坐标 0 16 3.359375 181.412500 8 7
11站 1 8 2.366250 180.950000 7 4
7克拉 0 13 3.601538 130.538462 8 5
@北京 1 6 1.238333 79.083333 6 4
BOBO自由城 1 27 2.565556 247.024444 12 5
... ... ... ... ... ... ...
龙锦苑东四区 0 16 2.041875 230.112500 13 11
龙锦苑二区 1 9 2.715556 280.722222 7 4
龙锦苑六区 0 14 2.880714 277.985714 12 9
龙锦苑四区 0 11 2.930909 289.272727 8 5
龙鼎园 1 20 1.990000 186.905000 14 11
index = np.random.permutation(len(data))
data_train = data.iloc[index[:int(0.7*len(data))]] # 对index切片
data_test = data.iloc[index[int(0.7*len(data))]:] # iloc切片
x_train, y_train = data_train[['taoshu', 'cjdanjia', 'cjzongjia', 'xingming', 'mendian']], data_train.zhangfu
x_test, y_test = data_test[['taoshu', 'cjdanjia', 'cjzongjia', 'xingming', 'mendian']], data_test.zhangfu
model2 = LogisticRegression()
model2.fit(x_train, y_train)
model2.score(x_test, y_test)
# output
0.630939226519337
data3 = data3.assign(louceng = data3.cjlouceng.map(lambda x:x.split('/')[1]))
data_lc = pd.crosstab(data3.xiaoqu, data3.louceng) # 交叉表
data = pd.merge(data, data_lc, left_index=True, right_index=True, how='left')
data
# output
zhangfu taoshu cjdanjia cjzongjia xingming mendian 中楼层 低楼层 地下室 高楼层
xiaoqu
10AM新坐标 0 16 3.359375 181.412500 8 7 8 5 0 3
11站 1 8 2.366250 180.950000 7 4 1 2 0 5
7克拉 0 13 3.601538 130.538462 8 5 11 2 0 0
@北京 1 6 1.238333 79.083333 6 4 1 4 0 1
BOBO自由城 1 27 2.565556 247.024444 12 5 13 7 0 7
... ... ... ... ... ... ... ... ... ... ...
龙锦苑东四区 0 16 2.041875 230.112500 13 11 6 2 0 8
龙锦苑二区 1 9 2.715556 280.722222 7 4 4 1 0 4
龙锦苑六区 0 14 2.880714 277.985714 12 9 8 5 0 1
龙锦苑四区 0 11 2.930909 289.272727 8 5 8 3 0 0
龙鼎园 1 20 1.990000 186.905000 14 11 11 3 0 6
index = np.random.permutation(len(data))
data_train = data.iloc[index[:int(0.7*len(data))]] # 对index切片
data_test = data.iloc[index[int(0.7*len(data))]:] # iloc切片
x_train, y_train = data_train[[x for x in data.columns if x!= 'zhangfu']], data_train.zhangfu
x_test, y_test = data_test[[x for x in data.columns if x!= 'zhangfu']], data_test.zhangfu
model3 = LogisticRegression()
model3.fit(x_train, y_train)
model3.score(x_test, y_test)
# output
0.6396508728179551
如果添加了两个相关的特征,模型的准确率会降低