本次实战项目的主要目的是分析北京二手房房价,项目源自博文:入门Python数据分析最好的实战项目(一)和入门Python数据分析最好的实战项目(二)。本篇文章仅记录博主在学习过程中的思路。


数据分析

首先我们要对数据进行分析,可分为以下几个主要步骤:

  • 导入数据
  • 检查缺失值情况并对表格进行简单处理
  • 数据可视化分析

这里我们重点要讲的是数据可视化分析,即对一些重要对特征逐个画图观察。

打开表格:

我们看到上述数据有 11 个特征变量,1 个目标变量 Price。11 个特征分别为:
Direction
District
Elevator
Floor
Garden
Id
Layout
Region
Renovation
Size
Year

我们分别对 Elevator, Floor, Layout, Region, Renovation, Size, Year 这 7 个特征进行可视化分析。

Elevator 特征分析

代码:

# Elevator 特征分析
miss_value = len(df.loc[(df['Elevator'].isnull()), 'Elevator'])
print('Elevator缺失值个数为:' + str(miss_value))# 移除表格中可能存在的错误的值
df['Elevator'] = df.loc[(df['Elevator']=='有电梯') | (df['Elevator']=='无电梯'), 'Elevator']# 以楼层大于6的有电梯,小于等于6层没有电梯为标准,填补缺失值
df.loc[(df['Floor']>6) & (df['Elevator'].isnull()), 'Elevator'] == '有电梯'
df.loc[(df['Floor']<=6) & (df['Elevator'].isnull()), 'Elevator'] == '无电梯'f, [ax1, ax2] = plt.subplots(1, 2, figsize=(20,10))
sns.countplot(df['Elevator'], ax=ax1)
ax1.set_title('有无电梯数量对比')
ax1.set_xlabel('是否有电梯')
ax1.set_ylabel('数量')sns.barplot(x='Elevator', y='Price', data=df, ax=ax2)
ax2.set_title('有无电梯价格对比')
ax2.set_xlabel('是否有电梯')
ax2.set_ylabel('价格')
plt.show()

执行结果:

分析目的:
分析有无电梯两种二手房对数量和价格。

使用方法:
采用seaborn完成可视化。

观察结果:
我们发现 Elevator 特征是有大量缺失值。一般有大量缺失值时,需要根据实际情况考虑。常用的方法有平均值/中位数填补法,直接移除,或根据其他特征建模预测等。

这里我们用填补法。由于有无电梯不是数值,不存在平均值和中位数,这里根据楼层 (Floor) 断有无电梯,一般的楼层大于 6 的都有电梯,而小于等于 6 层的一般都没有电梯。

在填补缺失值后继续观察,有电梯的二手房数量更多,且房价较高。

Floor 特征分析

代码:

# Floor 特征分析
f, ax1 = plt.subplots(figsize=(20,5))
sns.countplot(df['Floor'], ax=ax1)
ax1.set_title('各楼层二手房数量', fontsize=15)
ax1.set_xlabel('楼层')
ax1.set_ylabel('数量')
plt.show()

执行结果:

分析目的:
分析不同的楼层二手房数量。

使用方法:
采用seaborn完成可视化。

观察结果:
其中 6 层的二手房数量最多,但是单独的楼层特征没有什么意义,因为每个小区住房的总楼层数都不一样,我们需要知道楼层的相对高度。

此外,楼层与文化也有很重要的联系,比如在中国文化有七上八下,七层可能受欢迎等。一般来说中间楼层比较受欢迎,价格也高,底层和顶层受欢迎度较低,价格也相对较低。

楼层是一个非常复杂的特征,对房价影响也比较大。

Layout 特征分析

代码:

# Layout特征分析
f, ax1 = plt.subplots(figsize=(20, 20))
sns.countplot(y='Layout', data=df, ax=ax1)
ax1.set_title('房屋户型', fontsize=15)
ax1.set_xlabel('数量')
ax1.set_ylabel('户型')
plt.show()

执行结果:

分析目的:
分析不同户型的数量。

使用方法:
采用seaborn完成可视化。

观察结果:
这个特征分类下有很多不规则的命名,以上特征是不能作为机器学习模型的数据输入的,需要使用特征工程进行相应的处理。

Region 特征分析

代码:

df_house_count = df.groupby('Region')['Price'].count().sort_values(ascending=False).to_frame().reset_index()
df_house_mean = df.groupby('Region')['PerPrice'].mean().sort_values(ascending=False).to_frame().reset_index()f, [ax1, ax2, ax3] = plt.subplots(3, 1, figsize=(20,15))
sns.barplot(x='Region', y='PerPrice', palette='Blues_d', data=df_house_mean, ax=ax1)
ax1.set_title('北京各区二手房每平米单价对比', fontsize=15)
ax1.set_xlabel('区域')
ax1.set_ylabel('每平米单价')sns.barplot(x='Region', y='Price', palette="Greens_d", data=df_house_count, ax=ax2)
ax2.set_title('北京各大区二手房数量对比',fontsize=15)
ax2.set_xlabel('区域')
ax2.set_ylabel('数量')sns.boxplot(x='Region', y='Price', data=df, ax=ax3)
ax3.set_title('北京各大区二手房房屋总价',fontsize=15)
ax3.set_xlabel('区域')
ax3.set_ylabel('房屋总价')plt.show()

执行结果:

分析目的:
分析不同区域的房价和数量,并进行对比。

使用方法:
pandas的网络透视功能groupby分组排序。
区域特征可视化采用seaborn完成。
颜色使用调色板palette参数,颜色越浅数量越少,反之越多。

观察结果:
二手房每平方米单价对比:西城区的房价最贵均价大约 11 万/平,因为西城在二环以里,且是热门学区房的聚集地。其次是东城大约 10 万/平,然后是海淀大约 8.5 万/平,其它均低于 8 万/平。

二手房房数量对比:从数量统计上来看,海淀区和朝阳区二手房数量最多,约接近 3000 套,因为二者属于大区。其次是丰台区,近几年正在改造建设,需求量大。

二手房房屋总价对比:通过箱型图看到,各大区域房屋总价中位数都都在 1000 万以下,且房屋总价离散值较高,西城最高达到了 6000 万,说明房屋价格特征并不是理想的正态分布。

Renovation 特征分析

代码:

# Renovation 特征分析
df['Renovation'].value_counts()f, [ax1, ax2, ax3] = plt.subplots(1, 3, figsize=(20,5))
sns.countplot(df['Renovation'], ax=ax1)
sns.barplot(x='Renovation', y='Price', data=df, ax=ax2)
sns.boxplot(x='Renovation', y='Price', data=df, ax=ax3)
plt.show()

执行结果:

分析目的:
分析不同装修程度的二手房数量和房价。

使用方法:
采用seaborn完成可视化。

观察结果:
对于数量来说,精装修的二手房最多,简装其次;对于价格来说,毛坯房价格最高,其次是精装修的。

Size 特征分析

代码:

# Size特征分析
f, [ax1, ax2] = plt.subplots(1, 2, figsize=(15,5))# 建房时间分布情况
sns.distplot(df['Size'], bins=20, ax=ax1, color='r')
sns.kdeplot(df['Size'], ax=ax1, shade=True)# 建房时间和出售价格的关系
sns.regplot(x='Size', y='Price', data=df, ax=ax2)
plt.show()# 查看异常值
df.loc[df['Size'] < 10]
df.loc[df['Size'] > 1000]# 移除上述两种异常值
df = df[(df['Layout']!='叠拼别墅') & (df['Size']<1000)]# 重新进行可视化发现就没有明显的异常点
sns.regplot(x='Size', y='Price', data=df)
plt.show()

执行结果:

分析目的:
分析不同大小的二手房和价格的关系。

使用方法:
通过distplotkdeplot 绘制柱状图观察 Size 特征的分布情况,属于长尾类型的分布,这说明有很多面积很大且超出正常范围的二手房。

通过 regplot 绘制了 SizePrice 之间的散点图,发现 Size 特征基本与Price呈现线性关系,符合基本常识,面积越大,价格越高。

观察结果:
有两组明显的异常点:面积不到 10 平米但价格超出 10000 万和面积超过了 1000 平米价格很低两种情况。

经过查看发现这两组异常值分别是别墅和商用房,因此出现异常,故将其移除再次观察Size分布和Price关系。

这里也说明我们在观察数据的时候,要紧密结合实际业务需求来分析,才能得出更准确的结果。

Year 特征分析

代码:

# Year 特征分析
grid = sns.FacetGrid(df, row='Elevator', col='Renovation', palette='seismic', size=4)
grid.map(plt.scatter, 'Year', 'Price')
# grid.add_legend()

执行结果:

分析目的:
分析不同年代对房价变化的影响。

使用方法:
在 Renovation 和 Elevator 的分类条件下,使用 FacetGrid 分析 Year 特征

观察结果:
观察数据可视化图表可以看出,整个二手房房价趋势是随着时间增长而增长的,2000 年以后建造的二手房房价相较于 2000 年以前有很明显的价格上涨。此外,1980年之前几乎不存在有电梯二手房数据,说明1980年之前还没有大面积安装电梯,且在 1980 年之前无电梯二手房中,简装二手房占绝大多数,精装反而很少。

数据挖掘

特征工程

特征工程的目的是让这些特征更友好的作为模型的输入,处理数据的好坏会严重的影响模型性能。

这里我们对已有的 Layout 特征,Year 特征和 Direction 特征进行处理,创建新特征,删除无用特征,最后进行 One-hot 独热编码。

处理 Layout 特征

df['Layout'].value_counts()# 移除X房间X卫的格式 非民住
df = df.loc[df['Layout'].str.extract('^\d(.*?)\d.*?') == '室']
df.head()# 用 str.extract() 方法,将"室"和"厅"都提取出来,单独作为两个新特征
df['Layout_room_num'] = df['Layout'].str.extract('(^\d).*', expand=False).astype('int64')
df['Layout_hall_num'] = df['Layout'].str.extract('^\d.*?(\d).*', expand=False).astype('int64')

处理 Year 特征

# 将连续数值型特征 Year 离散化,做分箱处理
# 如何分箱还要看实际业务需求,这里为了方便,使用了pandas的 qcut 采用中位数进行分割,分割数为8等份
df['Year'] = pd.qcut(df['Year'], 8).astype('object')df['Year'].value_counts()

处理 Direction 特征

df['Direction'].value_counts()# 写函数 direct_func 来整理上面较乱的 Direction
def direct_func(x):if not isinstance(x,str):raise TypeErrorx = x.strip()x_len = len(x)x_list = pd.unique([y for y in x])if x_len != len(x_list):return 'no'if (x_len == 2) & (x not in d_list_two):m0 = x[0]m1 = x[1]return m1+m0elif (x_len == 3) & (x not in d_list_three):for n in d_list_three:if (x_list[0] in n) & (x_list[1] in n) & (x_list[2] in n):return nelif (x_len == 4) & (x not in d_list_four):return d_list_four[0]else:return x# 通过 apply() 方法将 Direction 数据格式转换
d_list_one = ['东','西','南','北']
d_list_two = ['东西','东南','东北','西南','西北','南北']
d_list_three = ['东西南','东西北','东南北','西南北']
d_list_four = ['东西南北']
df['Direction'] = df['Direction'].apply(direct_func)
df = df.loc[(df['Direction']!='no')&(df['Direction']!='nan')]df['Direction'].value_counts()

创建新特征

# 根据对业务的理解,定义新特征,然后观察这些新特征对模型有什么影响# 根据已有特征创建新特征
df['Layout_total_num'] = df['Layout_room_num'] + df['Layout_hall_num']
df['Size_room_ratio'] = df['Size']/df['Layout_total_num'] 

删除无用特征

df = df.drop(['Layout','PerPrice','Garden', 'District'], axis=1)df.head()

One-hot 独热编码
将定类的非数值型类型量化的一种方法,在pandas中使用 get_dummies() 方法实现。这里使用一个自定义的封装的函数实现了定类数据的自动量化处理。

def one_hot_encoder(df, nan_as_category = True):original_columns = list(df.columns)categorical_columns = [col for col in df.columns if df[col].dtype == 'object']df = pd.get_dummies(df, columns= categorical_columns, dummy_na= nan_as_category)new_columns = [c for c in df.columns if c not in original_columns]return df, new_columns# 对于object特征进行onehot编码
df, df_cat = one_hot_encoder(df)

特征相关性
对数据经过以上处理后,可以用 seabornheatmap 方法对特征相关性进行可视化。

colormap = plt.cm.RdBu
plt.figure(figsize=(20, 20))
sns.heatmap(df.corr(), linewidth=0.1, vmax=1.0, square=True,cmap=colormap, linecolor='white', annot=True)

heatmap 可以根据颜色观察特征的相关性。颜色偏红或者偏蓝都说明相关系数较大,即两个特征对于目标变量的影响程度相似,也就是说存在严重的重复信息,会造成过拟合现象。

我们能通过特征相关性分析,找出哪些特征有严重的重叠信息,然后择优选择。

这里还需要注意特征太多有可能会导致 heatmap 图画失败。

建模预测

本次建模主要方法为:使用Cart决策树的回归模型对二手房房价进行分析预测;使用交叉验证方法充分利用数据集进行训练,避免数据划分不均匀的影响;使用GridSearchCV方法优化模型参数;使用R2评分方法对模型预测评分。

数据划分

# 特征变量和目标变量
features = df.drop('Price', axis=1)
prices = df['Price']# 把分类特征都转成数值型后有{}行{}列
print('北京二手房房价有数据 {0} 条,字段 {1} 个' .format(*df.shape))# 将数据集划分为训练集与测试集
features = np.array(features)
prices = np.array(prices)# 导入 sklearn 进行训练测试集划分
from sklearn.model_selection import train_test_splitfeatures_train, features_test, prices_train, prices_test = train_test_split(features, prices, test_size=0.2, random_state=0)

建立模型

# 建立模型
from sklearn.model_selection import KFold
from sklearn.tree import DecisionTreeRegressor
from sklearn.metrics import make_scorer
from sklearn.model_selection import GridSearchCV# 通过交叉认证缓解数据集过拟合的现象
# 建立决策树回归模型
# 通过GridSearchCV找到最优深度参数(基于输入数据[X,y] 利于网格搜索找到最优的决策树模型)
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)# 网格搜索grid = grid.fit(X, y)return grid.best_estimator_

评估验证

# 计算 R2 分数
from sklearn.metrics import r2_scoredef performance_metric(y_true, y_predict):score = r2_score(y_true, y_predict)return score# 调参优化模型
# 通过可视化模型学习曲线,观察是否出现过拟合问题
# visuals 为自定义函数
import visuals as vs# 分析模型
vs.ModelLearning(features_train, prices_train)
vs.ModelComplexity(features_train, prices_train)
optimal = fit_model(features_train, prices_train)# 输出最优模型的参数 'max_depth'
print('最优模型的参数 max_depth 是: {} ' .format(optimal.get_params()['max_depth']))predicted_value = optimal.predict(features_test)
r2 = performance_metric(prices_test, predicted_value)# 每次交叉验证得到的数据集不同,因此每次运行的结果也不一定相同
print('最优模型在测试数据上 R^2 分数 {: .2f}' .format(r2))


可以看到,最理想模型的参数max_depth是 10,此时达到了偏差与方差的最优平衡。模型在测试数据上的 R2 分数为:0.77,即二手房房价预测的准确率。

以上,完成了一个项目的简单分析。可以改进的方向有以下 3 个:

  1. 爬取数据的准确性和完整性
  2. 特征的进一步提取
  3. 不同模型的融合与实验,以达到最优效果

不足之处,欢迎指正

数据挖掘实战项目——北京二手房房价分析相关推荐

  1. 【项目实战】北京二手房房价分析与预测

    项目简介 本项目根据个人需求进行北京二手房信息的数据分析,通过数据分析观察住房特征规律,利用机器学习模型进行简单的预测. 数据源 通过爬虫爬取第三方房屋中间商网站(链家和安居客)获取数据源,仅供学习使 ...

  2. 北京二手房房价分析(建模篇)

    数据科学俱乐部 中国数据科学家社区 本篇将继续上一篇数据分析用Python分析北京二手房房价之后进行数据挖掘建模预测,这两部分构成了一个简单的完整项目.结合两篇文章通过数据分析和挖掘的方法可以达到二手 ...

  3. python建筑案例_Python数据分析实战-链家北京二手房价分析

    前言 最近在自学Python,通过学习大家的分享案例,看到使用Python进行较多的主要4个方面:爬虫,数据处理,数据可视化以及机器学习建模.对我来说目标就是: 熟练使用numpy pandas 进行 ...

  4. 数据挖掘实战—商品零售购物篮分析

    文章目录 引言 一.数据探索性分析 1.数据质量分析 1.1 缺失值分析 1.2 异常值分析 1.3 重复数据分析 2.数据特征分析 2.1 描述性统计分析 2.2 分布分析 2.2.1 商品热销情况 ...

  5. SQL实战:上海二手房价分析

    数据来源可见我的上篇博文Python数据分析实战:上海二手房价分析.将CSV文件中的数据导入到Navicat中,导入过程中需选择"10008(MAC-Simplified Chinese G ...

  6. 商业大数据线下回归实验:北京二手房房价实验步骤(上)

    商业大数据线性回归实验:北京二手房房价实验步骤(上) 实验要求 (1)使用北京二手房房价.csv文件,创建一个工作流. (2) 用北京二手房房价.csv文件中的数据生成单位面积房价直方图.内部因素的单 ...

  7. 成都二手房房价分析-数据挖掘

    PricesDataAnalysis 本项目使用jupyter notebook开发,主要目的是分析成都二手房房价,项目地址. 数据:爬取二手房交易网站近期数据,成都各个区域交易热度较高的房屋信息. ...

  8. python二手房数据分析_Python 爬取北京二手房数据,分析北漂族买得起房吗? | 附完整源码...

    作者 徐麟 本文经授权转自公众号数据森麟(ID: shujusenlin) 房价高是北漂们一直关心的话题,本文就对北京的二手房数据进行了分析. 本文主要分为两部分:Python爬取赶集网北京二手房数据 ...

  9. 深圳二手房房价分析及预测

    分析目标: 通过处理后的房价数据,筛选对房价有显著影响的特征变量. 确定特征变量,建立深圳房价预测模型并对假设情景进行模拟 数据预处理 import pandas as pd import os fi ...

最新文章

  1. Ubuntu任务栏Tint2安装与使用
  2. python换零钱有多少种方案_Python3算法实例 1.2:动态规划 之 换零钱
  3. Dynamic Web Module 3.0 requires Java 1.6 or newer.
  4. 积分梯度:一种新颖的神经网络可视化方法
  5. vue模板html,VueJS模板
  6. php simplexmlelement array,php中SimpleXMLElement 对象转换为数组
  7. java递归求和 1 n_Java递归求和1+2+3+...+n实例详解
  8. Vivado 2015.4 安装教程(含license)
  9. 2019 美赛 A题
  10. USB:Type-A、Type-B、Type-C、miniUSB、microUSB接口类型区分
  11. 嗖嗖移动营业大厅(Java面向对象编程)
  12. iOS开发-舒尔特表
  13. 许知远在吴晓波《预见2019——国运70》2018年年终演讲上的精华
  14. pojo与entity
  15. 正式驻扎CSDN.hahaha
  16. HTML+CSS写个人简历
  17. maven-之Lifecycle详解
  18. Windows_U盘_SD卡_硬盘等存储介质无法完成格式化
  19. 有关xml中的xmlns
  20. 看新闻的时候,你们手机都用什么软件?

热门文章

  1. Win10输入法突然无法切换回中文输入
  2. 百度app红包? 百度全家桶?果断卸载
  3. Linux系统创建文件报错“E297: Write error in swap file“
  4. 音视频开发中的队列实现
  5. Hi3516a平台实现osd文字处理
  6. 软件测试工程师薪资是多少?
  7. java实现Excel文件解析---apache POI以及把汉字转化为拼音
  8. 根据ip查询地理位置
  9. 如果你到了20岁,还没到 25岁
  10. iris-v12 框架搭建二 mvc架构