赞
踩
从某房地产门户网站爬取城市区域二手房房产信息,存入数据库或文件,从数据库读取数据,进行分析、模型构建和房价预测。(本文为练习笔记总结,问题在所难免,待以后纠正和完善。)
以房/天/下成都天府新区二手房为抓取目标
import requests as rq from bs4 import BeautifulSoup import pandas as pd import numpy as np import seaborn as sns import matplotlib.pyplot as plt %matplotlib inline from sqlalchemy import create_engine from collections import Counter from IPython.display import Image import scipy.stats as stats from sklearn.model_selection import train_test_split from sklearn.model_selection import train_test_split # 先尝试获取首个页面的文本信息 url = 'http://cd.esf.fang.com/house-a016418/' res = rq.get(url) print(res.text[:100])
<!DOCTYPE html>
<html>
<head>
<title>【天府新区二手房|成都天府新区二手房出售】- 成都房天下</title>
<meta http-e
# 通过BeautifulSoup获得该页房产列表信息 soup = BeautifulSoup(res.text, 'html.parser') houses = soup.select('.shop_list dl') # 获取某个具体房屋页面上主要房屋指标信息 def getHouseInfo(url): house = {} soup = BeautifulSoup(rq.get(url).text, 'html.parser') res = soup.select('.tab-cont-right .trl-item1') #获取户型、建筑面积、单价、朝向、楼层和装修情况 for r in res: data = r.text.strip().split('\n') key = data[1].strip() if('朝向' in key): key = key.strip('进门') if('楼层' in key or '层数' in key): key = '楼层' if('装修程度' in key): key = '装修' house[key] = data[0].strip() # 获取小区名字 community = soup.select('.rcont .blue')[0].text house['小区名字'] = community # 获取总价 price = soup.select('.tab-cont-right .trl-item') house['总价'] = price[0].text return house # 打印该页对应房产的部分信息 print(getHouseInfo('http://cd.esf.fang.com/chushou/3_205701155.htm'))
{'户型': '3室2厅2卫', '建筑面积': '138平米', '单价': '24638元/平米', '朝向': '南', '楼层': '低层', '装修': '豪华装修', '小区名字': '阳光华苑', '总价': '340万'}
# 获取某房源列表页所有房产信息 import time domain = 'http://cd.esf.fang.com/' city = 'house-a016418/i3' def houses_at_page(i): page_url = domain + city + str(i) res = rq.get(page_url) soup = BeautifulSoup(res.text, 'html.parser') houses = soup.select('.shop_list dl') house_list = [] #遍历返回房屋信息 for house in houses: try: url = domain + house.select('.floatl a')[0]['href'] house = getHouseInfo(url) house_list.append(house) # 尽量避免反复快速访问页面爬取,推迟0.5秒 time.sleep(0.5) except Exception as e: print(e) data = pd.DataFrame(house_list) return data # 测试方法,打印数据集 data = houses_at_page(4) print(data)
单价 小区名字 建筑面积 总价 户型 朝向 楼层 装修
0 12892元/平米 南湖左岸 89.2平米 115万 3室2厅1卫 南 高层 简装修
1 15375元/平米 和泓半山 160平米 246万 3室2厅1卫 东 低层 豪华装修
2 14533元/平米 华银美景 75平米 109万 2室2厅1卫 暂无 高层 精装修
3 46205元/平米 蔚蓝卡地亚 606平米 2800万 5室2厅5卫 暂无 低层 豪华装修
4 16589元/平米 光明城市 92.23平米 153万 3室2厅1卫 南北 中层 毛坯
——(为了方便阅读这里只显示前五条记录)
# 创建数据链接
connect = create_engine('mysql+pymysql://root:root@localhost:3306/spider?charset-utf8')
# 房天下房产信息仅提供一百页
# 将每页房产信息存入数据库
for i in range(1, 101):
try:
data = houses_at_page(i)
except Exception as e:
print(e)
pd.io.sql.to_sql(data, 'house_price', connect, schema='spider', if_exists='append')
# 将全部房产信息每10页存入一个csv文件中 def houses_to_csv(): data = pd.DataFrame() prefix = 'houses_' for i in range(1, 101): try: data_a = houses_at_page(i) data = data_a.append(data) print('第{0}页信息当前文件抓取进度:{1}%'.format(i, i*10)) except Exception as e: print(e) if(i % 10 == 0): data.to_csv(prefix + str(i) + '.csv') data = pd.DataFrame() return data houses_to_csv()
conn = create_engine('mysql+pymysql://root:root@localhost:3306/spider?charset-utf8')
# 从数据库里获取所有房产信息
data = pd.io.sql.read_sql('select * from house_price', con=conn)
data.head()
index | 单价 | 小区名字 | 建筑面积 | 总价 | 户型 | 朝向 | 楼层 | 装修 | |
---|---|---|---|---|---|---|---|---|---|
0 | 0 | 11333元/平米 | 滨江和城 | 30平米 | 34万 | 2室1厅1卫 | 南北 | 中层 | 简装修 |
1 | 1 | 10000元/平米 | 滨江和城 | 45平米 | 45万 | 2室1厅1卫 | 南 | 中层 | 精装修 |
2 | 2 | 10667元/平米 | 三利麓山城 | 30平米 | 32万 | 1室1厅1卫 | 南北 | 中层 | 毛坯 |
3 | 3 | 16497元/平米 | 万科海悦汇城东区 | 58.8平米 | 97万 | 2室2厅1卫 | 西南 | 低层 | 精装修 |
4 | 4 | 26875元/平米 | \r\n 天府新区\r\n | 160平米 | 430万 | 4室2厅3卫 | 南 | 高层 | 简装修 |
data.tail()
index | 单价 | 小区名字 | 建筑面积 | 总价 | 户型 | 朝向 | 楼层 | 装修 | |
---|---|---|---|---|---|---|---|---|---|
3339 | 10 | 19167元/平米 | 万科海悦汇城西区 | 60平米 | 115万 | 2室2厅1卫 | 北 | 中层 | 精装修 |
3340 | 11 | 43925元/平米 | 麓湖生态城麒麟荟 | 428平米 | 1880万 | 5室3厅4卫 | 南 | 高层 | 简装修 |
3341 | 12 | 12083元/平米 | 洛森堡映山 | 120平米 | 145万 | 3室2厅2卫 | 南 | 高层 | 简装修 |
3342 | 13 | 87719元/平米 | 麓湖生态城黑蝶贝 | 1140平米 | 10000万 | 7室3厅6卫 | 南 | 低层 | 毛坯 |
3343 | 14 | 25758元/平米 | 麓山国际圣安德鲁 | 330平米 | 850万 | 5室2厅4卫 | 暂无 | 低层 | 毛坯 |
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3344 entries, 0 to 3343
Data columns (total 9 columns):
index 3344 non-null int64
单价 3344 non-null object
小区名字 3344 non-null object
建筑面积 3344 non-null object
总价 3344 non-null object
户型 3344 non-null object
朝向 3344 non-null object
楼层 3344 non-null object
装修 3344 non-null object
dtypes: int64(1), object(8)
memory usage: 235.2+ KB
data.小区名字.unique()
array(['滨江和城', '三利麓山城', '万科海悦汇城东区', '\r\n 天府新区\r\n ', '心怡紫晶城', '滨江天樾', '合能枫丹铂麓', '棠湖泊林城', '中铁骑士府邸', '海伦春天', '新鸿基悦城', '三都汇朝外', '原乡', '南湖半岛', '河畔新世界', '麓山国际麓镇帕萨迪纳', '中德英伦世邦', '德商华府天骄', '麓山国际圣安德鲁', '宏达世纪丽景', '碧桂园海昌天澜', '麓山国际茵特拉肯', '双华麓港', '心怡中丝园', '建发浅水湾', '府河音乐花园', '麓山国际社区云堤曦岸', '恒大天府半岛二期', '中德麓府', '兰桥尚舍', '麓山国际别墅', '麓山国际社区茵特拉肯', '和泓半山', '麓湖生态城麒麟荟', '麓湖生态城白玉台', '瑞升橡树林华府', '蔚蓝卡地亚', '麓山国际悦林湖', '恒大天府半岛', '麓湖生态城黑珍珠', '佳兆业君汇上品', '麓山国际塞尔维蒙', '石化家园', '保利叶语', '鑫苑鑫都汇', '美城悦荣府别墅', '成都玩家', '麓山国际长岛', '麓湖生态城蓝花屿', '融创Nano公馆', '戛纳湾金棕榈', '九龙仓时代上城', '麓湖生态城隐溪岸', '南湖世纪', '雅居乐富春山居', '中铁诺德壹号', '水印城', '北辰南湖香麓', '洛森堡映山', '南湖国际社区三期', '麓山国际半月湾', '华阳滨河花园', '麓山国际逸翠谷', '麓山国际碧湖岸', '三利宅院白云渡', '铂雅苑', '黄金海岸', '麓山国际', '光明城市', '麓山国际黑鹰庄园', '南湖左岸', '天投北鑫苑', '麓山国际拉佩维尔', '南阳盛世', '远大中央公园', '南湖国际社区二期', '蜀郡一期', '香山半岛', '欣宇都市港湾', '双峰嶺', '宏达世纪锦城', '万科海悦汇城西区', '恒大名都', '麓山国际香溪堤', '麓山国际圣芭芭拉', '麓山国际社区云曦台', '德商御府天骄', '麓湖生态城云树', '美城悦荣府', '棠湖泊林城别墅', '雅居乐花园一期', '中海左岸', '秦皇帝锦', '蓝山美树', '复地御香山', '双兴名邸四季春天', '和贵馨城', '融创南湖逸家', '麓山国际碧影溪', '麓山国际翠云岭', '戛纳湾滨江', '亚丁小镇', '万锦城', '蜀郡又一城', '宏信南樾', '麓山国际橡树坡', '中海右岸', '和贵南山上', '洛森堡蝶郡', '洛森堡新殿', '景茂城果', '青南美湾', '雅居乐十里花巷', '麓湖生态城沉香谷', '麓山国际叠溪谷', '蜀郡别墅', '保利锦江里', '麓山国际圆石滩', '麓湖生态城黑蝶贝', '恺信时代天城', '美高登A座', '枫渡莱茵', '麓山国际solo', '鸿阁一号', '南阳锦城', '凯华丽景', '成都雅居乐花园别墅', '蓝山国际爵悦半岛', '麓湖生态城澜语溪岸', '海昌天澜别墅', '棕榈南岸', '南湖国际社区四期', '麓山国际黑钻山庄', '欧香小镇别墅', '锦官丽城亲水湾', '三利云锦', '蓝山国际伯爵山', '蓝润ISC', '蓝岸丽景', '嘉美地', '天府美岸', '美城云庭', '长冶南阳锦城香樟阁', '慕和南道', '永泰雅居', '碧桂园海昌天澜别墅', '鸿阁新座', '心怡德盛苑', '南湖国际社区一期', '华银美景', '油建苑', '麓山印象', '丽都新城一期', '家益欣城', '地源吾舍', '华阳府河名居', '成南领寓', '楠域丽景', '麓山国际黑檀庄园', '凯莱丽景雅筑', '华阳花苑', '麓湖生态城玲珑屿', '万科翡翠公园', '融创玖棠府', '金南园', '六菱小区', '阳光华苑', '麓岭汇', '大城际', '戛纳湾畔', '三利麓山城别墅', '顺发苑', '翠拥天地', '明珠怡园', '阳光华庭', '欣雨苑', '金城花园', '保利御景台', '瑞雪港湾', '麓湖生态城原溪岸'], dtype=object)
data.户型.unique()
array(['2室1厅1卫', '1室1厅1卫', '2室2厅1卫', '4室2厅3卫', '3室2厅2卫', '4室2厅2卫',
'4室3厅4卫', '2室2厅2卫', '3室1厅1卫', '5室3厅4卫', '3室2厅1卫', '5室2厅4卫',
'4室3厅2卫', '4室3厅3卫', '4室2厅4卫', '9室5厅8卫', '5室2厅3卫', '5室3厅3卫',
'6室3厅5卫', '4室1厅1卫', '4室1厅2卫', '5室1厅3卫', '5室3厅5卫', '3室3厅3卫',
'4室5厅4卫', '4室4厅4卫', '6室3厅3卫', '5室3厅2卫', '7室6厅7卫', '3室2厅3卫',
'8室5厅6卫', '5室2厅5卫', '3室3厅1卫', '8室3厅8卫', '6室4厅5卫', '4室3厅5卫',
'6室2厅5卫', '6室2厅4卫', '6室2厅7卫', '6室3厅6卫', '6室3厅4卫', '6室4厅6卫',
'6室4厅4卫', '6室1厅1卫', '6室2厅6卫', '7室4厅6卫', '5室2厅2卫', '9室1厅1卫',
'5室4厅4卫', '8室6厅7卫', '2室2厅3卫', '5室1厅5卫', '5室3厅1卫', '3室4厅2卫',
'3室1厅2卫', '7室3厅5卫', '5室4厅5卫', '8室4厅8卫', '4室2厅5卫', '4室1厅3卫',
'7室3厅6卫', '暂无', '6室3厅1卫', '1室2厅1卫', '7室3厅7卫', '5室4厅2卫', '7室5厅6卫',
'7室3厅4卫', '8室4厅4卫', '5室4厅3卫', '5室2厅6卫', '7室2厅5卫', '4室2厅1卫',
'5室3厅6卫', '5室1厅4卫', '3室3厅2卫', '4室21厅4卫', '9室4厅7卫', '7室2厅6卫',
'6室5厅3卫', '7室4厅4卫', '7室2厅3卫', '6室5厅5卫', '5室5厅2卫'], dtype=object)
data.朝向.unique()
array(['南北', '南', '西南', '西', '东', '东南', '暂无', '东西', '北', '东北', '西北'],
dtype=object)
data.groupby(by=['朝向'], as_index=False).count().sort_values(by=['朝向'])
朝向 | index | 单价 | 小区名字 | 建筑面积 | 总价 | 户型 | 楼层 | 装修 | |
---|---|---|---|---|---|---|---|---|---|
0 | 东 | 370 | 370 | 370 | 370 | 370 | 370 | 370 | 370 |
1 | 东北 | 35 | 35 | 35 | 35 | 35 | 35 | 35 | 35 |
2 | 东南 | 196 | 196 | 196 | 196 | 196 | 196 | 196 | 196 |
3 | 东西 | 55 | 55 | 55 | 55 | 55 | 55 | 55 | 55 |
4 | 北 | 84 | 84 | 84 | 84 | 84 | 84 | 84 | 84 |
5 | 南 | 1318 | 1318 | 1318 | 1318 | 1318 | 1318 | 1318 | 1318 |
6 | 南北 | 659 | 659 | 659 | 659 | 659 | 659 | 659 | 659 |
7 | 暂无 | 345 | 345 | 345 | 345 | 345 | 345 | 345 | 345 |
8 | 西 | 118 | 118 | 118 | 118 | 118 | 118 | 118 | 118 |
9 | 西北 | 40 | 40 | 40 | 40 | 40 | 40 | 40 | 40 |
10 | 西南 | 124 | 124 | 124 | 124 | 124 | 124 | 124 | 124 |
data.楼层.unique()
array(['中层', '低层', '高层'], dtype=object)
data.装修.unique()
array(['简装修', '精装修', '毛坯', '豪华装修', '中装修', '暂无'], dtype=object)
data.groupby(by=['装修'], as_index=False).count()
装修 | index | 单价 | 小区名字 | 建筑面积 | 总价 | 户型 | 朝向 | 楼层 | |
---|---|---|---|---|---|---|---|---|---|
0 | 中装修 | 76 | 76 | 76 | 76 | 76 | 76 | 76 | 76 |
1 | 暂无 | 6 | 6 | 6 | 6 | 6 | 6 | 6 | 6 |
2 | 毛坯 | 1318 | 1318 | 1318 | 1318 | 1318 | 1318 | 1318 | 1318 |
3 | 简装修 | 536 | 536 | 536 | 536 | 536 | 536 | 536 | 536 |
4 | 精装修 | 1039 | 1039 | 1039 | 1039 | 1039 | 1039 | 1039 | 1039 |
5 | 豪华装修 | 369 | 369 | 369 | 369 | 369 | 369 | 369 | 369 |
# index列只用于索引,无助于预测,可以删除
del data['index']
# 小区名字一列暂时未发现参考价值,等以后结合具体地理位置区块分类再处理
del data['小区名字']
# 将带有单位的列转变成浮点型
data['单价'] = data['单价'].apply(lambda x:x.replace('元/平米', '')).astype(float)
data['建筑面积'] = data['建筑面积'].apply(lambda x:x.replace('平米', '')).astype(float)
data['总价'] = data['总价'].apply(lambda x:x.replace('万', '')).astype(float)
# 户型一列的“暂无”数量较少,暂且填充为众数
temp = data.户型.mode()[0]
data.loc[data.户型 == '暂无', '户型'] = temp
data.户型.unique()
array(['2室1厅1卫', '1室1厅1卫', '2室2厅1卫', '4室2厅3卫', '3室2厅2卫', '4室2厅2卫',
'4室3厅4卫', '2室2厅2卫', '3室1厅1卫', '5室3厅4卫', '3室2厅1卫', '5室2厅4卫',
'4室3厅2卫', '4室3厅3卫', '4室2厅4卫', '9室5厅8卫', '5室2厅3卫', '5室3厅3卫',
'6室3厅5卫', '4室1厅1卫', '4室1厅2卫', '5室1厅3卫', '5室3厅5卫', '3室3厅3卫',
'4室5厅4卫', '4室4厅4卫', '6室3厅3卫', '5室3厅2卫', '7室6厅7卫', '3室2厅3卫',
'8室5厅6卫', '5室2厅5卫', '3室3厅1卫', '8室3厅8卫', '6室4厅5卫', '4室3厅5卫',
'6室2厅5卫', '6室2厅4卫', '6室2厅7卫', '6室3厅6卫', '6室3厅4卫', '6室4厅6卫',
'6室4厅4卫', '6室1厅1卫', '6室2厅6卫', '7室4厅6卫', '5室2厅2卫', '9室1厅1卫',
'5室4厅4卫', '8室6厅7卫', '2室2厅3卫', '5室1厅5卫', '5室3厅1卫', '3室4厅2卫',
'3室1厅2卫', '7室3厅5卫', '5室4厅5卫', '8室4厅8卫', '4室2厅5卫', '4室1厅3卫',
'7室3厅6卫', '6室3厅1卫', '1室2厅1卫', '7室3厅7卫', '5室4厅2卫', '7室5厅6卫',
'7室3厅4卫', '8室4厅4卫', '5室4厅3卫', '5室2厅6卫', '7室2厅5卫', '4室2厅1卫',
'5室3厅6卫', '5室1厅4卫', '3室3厅2卫', '4室21厅4卫', '9室4厅7卫', '7室2厅6卫',
'6室5厅3卫', '7室4厅4卫', '7室2厅3卫', '6室5厅5卫', '5室5厅2卫'], dtype=object)
data[['室', '厅', '卫']] = data.户型.str.extract('(\d+)室(\d+)厅(\d+)卫')
D:\Anaconda3\lib\site-packages\ipykernel_launcher.py:1: FutureWarning: currently extract(expand=None) means expand=False (return Index/Series/DataFrame) but in a future version of pandas this will be changed to expand=True (return DataFrame)
"""Entry point for launching an IPython kernel.
data.室 = data.室.astype(float)
data.厅 = data.厅.astype(float)
data.卫 = data.卫.astype(float)
del data['户型']
# 装修一列的“暂无”数量较少,暂且填充为众数
temp = data.装修.mode()[0]
data.loc[data.装修 == '暂无', '装修'] = temp
data.groupby(by='装修', as_index=False).count()
装修 | 单价 | 建筑面积 | 总价 | 朝向 | 楼层 | 室 | 厅 | 卫 | |
---|---|---|---|---|---|---|---|---|---|
0 | 中装修 | 76 | 76 | 76 | 76 | 76 | 76 | 76 | 76 |
1 | 毛坯 | 1324 | 1324 | 1324 | 1324 | 1324 | 1324 | 1324 | 1324 |
2 | 简装修 | 536 | 536 | 536 | 536 | 536 | 536 | 536 | 536 |
3 | 精装修 | 1039 | 1039 | 1039 | 1039 | 1039 | 1039 | 1039 | 1039 |
4 | 豪华装修 | 369 | 369 | 369 | 369 | 369 | 369 | 369 | 369 |
map_decor = {'毛坯': 0, '简装修': 1, '中装修': 2, '精装修': 3, '豪华装修': 4}
data.装修 = data.装修.map(map_decor)
#
map_floor = {'低层': 0, '中层': 1, '高层': 2}
data.楼层 = data.楼层.map(map_floor)
map_ort = {'南北': 0, '东西': 1, '南': 2, '东南': 3, '西南': 4, '东': 5, '西': 6, '东北': 7, '西北': 8, '北': 9, '暂无': 10}
data.朝向 = data.朝向.map(map_ort)
data.head()
单价 | 建筑面积 | 总价 | 朝向 | 楼层 | 装修 | 室 | 厅 | 卫 | |
---|---|---|---|---|---|---|---|---|---|
0 | 11333.0 | 30.0 | 34.0 | 0 | 1 | 1 | 2.0 | 1.0 | 1.0 |
1 | 10000.0 | 45.0 | 45.0 | 2 | 1 | 3 | 2.0 | 1.0 | 1.0 |
2 | 10667.0 | 30.0 | 32.0 | 0 | 1 | 0 | 1.0 | 1.0 | 1.0 |
3 | 16497.0 | 58.8 | 97.0 | 4 | 0 | 3 | 2.0 | 2.0 | 1.0 |
4 | 26875.0 | 160.0 | 430.0 | 2 | 2 | 1 | 4.0 | 2.0 | 3.0 |
data.describe()
单价 | 建筑面积 | 总价 | 朝向 | 楼层 | 装修 | 室 | 厅 | 卫 | |
---|---|---|---|---|---|---|---|---|---|
count | 3344.000000 | 3344.000000 | 3344.000000 | 3344.000000 | 3344.000000 | 3344.000000 | 3344.000000 | 3344.000000 | 3344.000000 |
mean | 21775.498804 | 210.135939 | 625.367285 | 3.320574 | 0.773624 | 1.579246 | 3.558014 | 2.172548 | 2.460227 |
std | 13051.462878 | 176.833842 | 1056.908959 | 3.058916 | 0.790618 | 1.523080 | 1.251352 | 0.689097 | 1.350896 |
min | 7105.000000 | 20.000000 | 26.000000 | 0.000000 | 0.000000 | 0.000000 | 1.000000 | 1.000000 | 1.000000 |
25% | 13842.750000 | 90.932500 | 135.000000 | 2.000000 | 0.000000 | 0.000000 | 3.000000 | 2.000000 | 1.000000 |
50% | 16941.500000 | 141.000000 | 210.000000 | 2.000000 | 1.000000 | 1.000000 | 3.000000 | 2.000000 | 2.000000 |
75% | 26342.500000 | 280.352500 | 640.000000 | 5.000000 | 1.000000 | 3.000000 | 4.000000 | 2.000000 | 3.000000 |
max | 134328.000000 | 2340.000000 | 12000.000000 | 10.000000 | 2.000000 | 4.000000 | 9.000000 | 21.000000 | 8.000000 |
data.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 3344 entries, 0 to 3343
Data columns (total 9 columns):
单价 3344 non-null float64
建筑面积 3344 non-null float64
总价 3344 non-null float64
朝向 3344 non-null int64
楼层 3344 non-null int64
装修 3344 non-null int64
室 3344 non-null float64
厅 3344 non-null float64
卫 3344 non-null float64
dtypes: float64(6), int64(3)
memory usage: 235.2 KB
# 让图可以显示中文
plt.rcParams['font.sans-serif'] = ['SimHei']
#plt.figure()
# 绘制线性回归散点图
otl = sns.lmplot('建筑面积', '总价', data, fit_reg=False)
# 获取总价前三名的记录
data.sort_values(by='建筑面积', ascending=False).head(3)
单价 | 建筑面积 | 总价 | 朝向 | 楼层 | 装修 | 室 | 厅 | 卫 | |
---|---|---|---|---|---|---|---|---|---|
2587 | 27350.0 | 2340.0 | 6400.0 | 5 | 1 | 0 | 1.0 | 1.0 | 1.0 |
515 | 56693.0 | 1270.0 | 7200.0 | 2 | 0 | 4 | 9.0 | 1.0 | 1.0 |
550 | 83325.0 | 1200.0 | 9999.0 | 5 | 1 | 0 | 8.0 | 6.0 | 7.0 |
# 将异常值移除
data.drop(data[(data['建筑面积'] >= 1500)].index, inplace=True)
data.sort_values(by='建筑面积', ascending=False).head(3)
单价 | 建筑面积 | 总价 | 朝向 | 楼层 | 装修 | 室 | 厅 | 卫 | |
---|---|---|---|---|---|---|---|---|---|
515 | 56693.0 | 1270.0 | 7200.0 | 2 | 0 | 4 | 9.0 | 1.0 | 1.0 |
550 | 83325.0 | 1200.0 | 9999.0 | 5 | 1 | 0 | 8.0 | 6.0 | 7.0 |
926 | 82969.0 | 1145.0 | 9500.0 | 2 | 0 | 0 | 7.0 | 3.0 | 6.0 |
# 重新绘制图形
plt.figure()
sns.lmplot('建筑面积', '总价', data, fit_reg=False);
plt.xlim(0,1500)
plt.ylim(0,13000);
<matplotlib.figure.Figure at 0x1c48f0b8>
# 绘制价格分布图
plt.figure(figsize=(9, 6))
sns.distplot(data.总价)
plt.title('总价分布')
plt.ylabel('频率')
print("偏度为{:.3f}".format(data['总价'].skew()))
# 绘制概率图
# 正常显示坐标负值
plt.figure(figsize=(9, 6))
plt.rcParams['axes.unicode_minus'] = False
stats.probplot(data['总价'], plot=plt)
plt.show()
D:\Anaconda3\lib\site-packages\scipy\stats\stats.py:1633: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
return np.add.reduce(sorted[indexer] * weights, axis=axis) / sumval
偏度为4.671
price_data = data.总价
data = data.drop('总价',axis=1)
data.insert(0,'总价',price_data)
x, y = data.ix[:,1:], data.ix[:,0]
x_train, x_test, y_train, y_test = train_test_split(x, y, test_size=0.3, random_state=0)
D:\Anaconda3\lib\site-packages\ipykernel_launcher.py:1: DeprecationWarning:
.ix is deprecated. Please use
.loc for label based indexing or
.iloc for positional indexing
See the documentation here:
http://pandas.pydata.org/pandas-docs/stable/indexing.html#ix-indexer-is-deprecated
"""Entry point for launching an IPython kernel.
plt.figure(figsize=(9, 6))
plt.scatter(x_train.建筑面积, y_train)
plt.ylabel('总价')
plt.xlabel('建筑面积')
Text(0.5,0,'建筑面积')
sns.distplot(y_train)
plt.ylabel('频率')
plt.title('分布图')
plt.show()
D:\Anaconda3\lib\site-packages\scipy\stats\stats.py:1633: FutureWarning: Using a non-tuple sequence for multidimensional indexing is deprecated; use `arr[tuple(seq)]` instead of `arr[seq]`. In the future this will be interpreted as an array index, `arr[np.array(seq)]`, which will result either in an error or a different result.
return np.add.reduce(sorted[indexer] * weights, axis=axis) / sumval
stats.probplot(y_train, plot=plt)
((array([-3.43509518, -3.18695128, -3.04948019, ..., 3.04948019,
3.18695128, 3.43509518]),
array([ 26., 27., 28., ..., 9500., 9500., 9999.])),
(751.4122330833427, 625.6583461538461, 0.7313168979168443))
print('偏度为:{0}'.format(y_train.skew()))
偏度为:4.258903339034095
data_train = x_train.join(y_train)
data_train.head()
单价 | 建筑面积 | 朝向 | 楼层 | 装修 | 室 | 厅 | 卫 | 总价 | |
---|---|---|---|---|---|---|---|---|---|
563 | 14157.0 | 89.00 | 0 | 0 | 3 | 3.0 | 2.0 | 2.0 | 126.0 |
2025 | 10263.0 | 114.00 | 0 | 2 | 0 | 3.0 | 2.0 | 2.0 | 117.0 |
3253 | 13478.0 | 92.00 | 2 | 1 | 3 | 3.0 | 1.0 | 2.0 | 124.0 |
921 | 61947.0 | 565.00 | 10 | 2 | 4 | 6.0 | 3.0 | 6.0 | 3500.0 |
1770 | 26889.0 | 185.95 | 2 | 2 | 3 | 4.0 | 3.0 | 3.0 | 500.0 |
plt.figure(figsize=(12, 10))
corr = data_train.corr()
#num = data.shape[1] - 1
#col = corr.nlargest(num, '总价')['总价'].index
col = corr.sort_values('总价', ascending=False).index
coeff = np.corrcoef(data[col].values.T)
sns.heatmap(coeff, annot=True, xticklabels=col.values, yticklabels=col.values, linewidth=0.1, cmap=plt.cm.jet, linecolor='white')
<matplotlib.axes._subplots.AxesSubplot at 0x1d7ff390>
sns.pairplot(data_train[col], size=2);
from sklearn.model_selection import KFold from sklearn.tree import DecisionTreeRegressor from sklearn.metrics import make_scorer from sklearn.model_selection import GridSearchCV from sklearn.metrics import r2_score # 利用GridSearchCV计算最优解 def fit_model(X, y): cross_validator = KFold(10, shuffle=True) regressor = DecisionTreeRegressor() params = {'max_depth': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]} scoring_fnc = make_scorer(performance_metric) grid = GridSearchCV(estimator=regressor, param_grid=params, scoring=scoring_fnc, cv=cross_validator) # 用输入数据[X, y]进行网格搜索 grid = grid.fit(X, y) return grid.best_estimator_ # 计算R2 def performance_metric(y_true, y_predict): score = r2_score(y_true, y_predict) return score
使用了 KFold 方法减缓过拟合,GridSearchCV 方法进行最优参数自动搜查,最后使用R2评分来给模型打分。
from https://raw.githubusercontent.com/udacity/machine-learning/master/projects/boston_housing/visuals.py
这里借用了visuals.py代码,为方便阅读暂不放进内容,请自行下载查看
ModelLearning(x_train, y_train)
ModelComplexity(x_train, y_train)
optimal_reg1 = fit_model(x_train, y_train)
# 打印最优模型参数
print("最优模型参数max_depth={}".format(optimal_reg1.get_params()['max_depth']))
predicted_value = optimal_reg1.predict(x_test)
r2 = performance_metric(y_test, predicted_value)
# 打印最优模型R^2分数
print("最优模型在测试数据上的R^2分数={:, .2f}。".format(r2))
最优模型参数max_depth=10
最优模型在测试数据上的R^2分数=0.97
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。