做者:xiaoyupython
微信公众号:Python数据科学bash
知乎:python数据分析师微信
目的:本篇给你们介绍一个数据分析的初级项目,目的是经过项目了解如何使用Python进行简单的数据分析。网络
数据源:博主经过爬虫采集的链家全网北京二手房数据(公众号后台回复 二手房数据 即可获取)。机器学习
首先导入要使用的科学计算包numpy
,pandas
,可视化matplotlib
,seaborn
,以及机器学习包sklearn
。性能
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib as mpl
import matplotlib.pyplot as plt
from IPython.display import display
plt.style.use("fivethirtyeight")
sns.set_style({'font.sans-serif':['simhei','Arial']})
%matplotlib inline
# 检查Python版本
from sys import version_info
if version_info.major != 3:
raise Exception('请使用Python 3 来完成此项目')
复制代码
而后导入数据,并进行初步的观察,这些观察包括了解数据特征的缺失值,异常值,以及大概的描述性统计。学习
# 导入链家二手房数据
lianjia_df = pd.read_csv('lianjia.csv')
display(lianjia_df.head(n=2))
复制代码
初步观察到一共有11
个特征变量,Price
在这里是咱们的目标变量,而后咱们继续深刻观察一下。ui
# 检查缺失值状况
lianjia_df.info()
复制代码
23677
条数据,其中
Elevator
特征有明显的缺失值。
lianjia_df.describe()
复制代码
上面结果给出了特征值是数值的一些统计值,包括平均数,标准差,中位数,最小值,最大值,25%分位数,75%分位数。这些统计结果简单直接,对于初始了解一个特征好坏很是有用,好比咱们观察到 Size 特征
的最大值为1019平米,最小值为2平米,那么咱们就要思考这个在实际中是否是存在的,若是不存在没有意义,那么这个数据就是一个异常值,会严重影响模型的性能。人工智能
固然,这只是初步观察,后续咱们会用数据可视化来清晰的展现,并证明咱们的猜想。spa
# 添加新特征房屋均价
df = lianjia_df.copy()
df['PerPrice'] = lianjia_df['Price']/lianjia_df['Size']
# 从新摆放列位置
columns = ['Region', 'District', 'Garden', 'Layout', 'Floor', 'Year', 'Size', 'Elevator', 'Direction', 'Renovation', 'PerPrice', 'Price']
df = pd.DataFrame(df, columns = columns)
# 从新审视数据集
display(df.head(n=2))
复制代码
咱们发现Id
特征其实没有什么实际意义,因此将其移除。因为房屋单价分析起来比较方便,简单的使用总价/面积就可获得,因此增长一个新的特征 PerPrice
(只用于分析,不是预测特征)。另外,特征的顺序也被调整了一下,看起来比较舒服。
对于区域特征,咱们能够分析不一样区域房价和数量的对比。
# 对二手房区域分组对比二手房数量和每平米房价
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
参数,颜色渐变,越浅说明越少,反之越多。 能够观察到:
f, [ax1,ax2] = plt.subplots(1, 2, figsize=(15, 5))
# 建房时间的分布状况
sns.distplot(df['Size'], bins=20, ax=ax1, color='r')
sns.kdeplot(df['Size'], shade=True, ax=ax1)
# 建房时间和出售价格的关系
sns.regplot(x='Size', y='Price', data=df, ax=ax2)
plt.show()
复制代码
distplot
和 kdeplot
绘制柱状图观察 Size 特征的分布状况,属于长尾类型的分布,这说明了有不少面积很大且超出正常范围的二手房。regplot
绘制了 Size 和 Price 之间的散点图,发现 Size 特征基本与Price呈现线性关系,符合基本常识,面积越大,价格越高。可是有两组明显的异常点:1. 面积不到10平米,可是价格超出10000万;2. 一个点面积超过了1000平米,价格很低,须要查看是什么状况。df.loc[df['Size']< 10]
复制代码
通过查看发现这组数据是别墅,出现异常的缘由是因为别墅结构比较特殊(无朝向无电梯),字段定义与二手商品房不太同样致使爬虫爬取数据错位。也因别墅类型二手房不在咱们的考虑范围以内,故将其移除再次观察Size分布和Price关系。
df.loc[df['Size']>1000]
复制代码
df = df[(df['Layout']!='叠拼别墅')&(df['Size']<1000)]
复制代码
从新进行可视化发现就没有明显的异常点了。
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()
复制代码
df['Renovation'].value_counts()
复制代码
精装 11345
简装 8497
其余 3239
毛坯 576
南北
20
Name: Renovation, dtype: int64
发现Renovation装修特征中居然有南北,它属于朝向的类型,多是由于爬虫过程当中一些信息位置为空,致使“Direction”朝向特征出如今这里,因此须要清除
或替换掉
。
# 去掉错误数据“南北”,由于爬虫过程当中一些信息位置为空,致使“Direction”的特征出如今这里,须要清除或替换
df['Renovation'] = df.loc[(df['Renovation'] != '南北'), 'Renovation']
# 画幅设置
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()
复制代码
初探数据的时候,咱们发现 Elevator 特征是有大量缺失值的,这对于咱们是十分不利的,首先咱们先看看有多少缺失值:
misn = len(df.loc[(df['Elevator'].isnull()), 'Elevator'])
print('Elevator缺失值数量为:'+ str(misn))
复制代码
Elevator 缺失值数量为:8237
这么多的缺失值怎么办呢?这个须要根据实际状况考虑,经常使用的方法有平均值/中位数填补法,直接移除,或者根据其余特征建模预测等。
这里咱们考虑填补法,可是有无电梯不是数值,不存在平均值和中位数,怎么填补呢?这里给你们提供一种思路:就是根据楼层 Floor 来判断有无电梯,通常的楼层大于6的都有电梯,而小于等于6层的通常都没有电梯。有了这个标准,那么剩下的就简单了。
# 因为存在个别类型错误,如简装和精装,特征值错位,故须要移除
df['Elevator'] = df.loc[(df['Elevator'] == '有电梯')|(df['Elevator'] == '无电梯'), 'Elevator']
# 填补Elevator缺失值
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('有无电梯数量对比',fontsize=15)
ax1.set_xlabel('是否有电梯')
ax1.set_ylabel('数量')
sns.barplot(x='Elevator', y='Price', data=df, ax=ax2)
ax2.set_title('有无电梯房价对比',fontsize=15)
ax2.set_xlabel('是否有电梯')
ax2.set_ylabel('总价')
plt.show()
复制代码
grid = sns.FacetGrid(df, row='Elevator', col='Renovation', palette='seismic',size=4)
grid.map(plt.scatter, 'Year', 'Price')
grid.add_legend()
复制代码
在Renovation和Elevator的分类条件下,使用 FaceGrid
分析 Year 特征,观察结果以下:
f, ax1= plt.subplots(figsize=(20,5))
sns.countplot(x='Floor', data=df, ax=ax1)
ax1.set_title('房屋户型',fontsize=15)
ax1.set_xlabel('数量')
ax1.set_ylabel('户型')
plt.show()
复制代码
本次分享旨在让你们了解如何用Python作一个简单的数据分析,对于刚刚接触数据分析的朋友无疑是一个很好的练习。不过,这个分析还存在不少问题须要解决,好比:
更多内容会慢慢介绍和分享,敬请期待。
关注微信公众号Python数据科学,获取 120G
人工智能 学习资料。