# 导入需要的库:科学计算包numpy, pandas 可视化包matplotlib, seaborn 机器学习包 sklearn
import numpy as np
import pandas as pd
import matplotlib as mpl
import seaborn as sns
import matplotlib.pyplot as plt
from IPython.display import display
# 可以在引入Matplotlib后通过运行plt.style.use(style_name)来修改绘图的风格。所有可用的风格在plt.style.available中列出。
# 比如,尝试使用plt.style.use('fivethirtyeight')、plt.style.use('ggplot')或者plt.style.use('seaborn-dark')。
# 为了更好玩,可以运行plt.xkcd(),然后尝试绘制一些别的图形。
plt.style.use("fivethirtyeight")
# 防止出现中文乱码,应修改 seabron 配置文件
sns.set_style({'font.sans-serif':['simhei','Arial']})
%matplotlib inline
# 导入数据,并进行初步观察
lianjia_df = pd.read_csv('lianjia.csv')
display(lianjia_df.head())
- Direction 方向
- District 地址
- Elevator 是否有电梯
- Floor 楼层
- Garden 家园
- Id ID
- Layout 布局
- Price 价格
- Region 地区
- Renovation 装修
- Size 面积
- Year 年份
lianjia_df.info()
数据总共有23677条,Elevator 字段有缺失值。
# 对数据进行描述性分析
lianjia_df.describe()
price 平均数 610
标准差 411
中位数 499
最小值 60
最大值 6000
这些统计结果简单直接,对于初始了解一个特征好坏非常有用,比如我们观察到 Size 特征 的最大值为1019平米,最小值为2平米,那么我们就要思考这个在实际中是不是存在的,如果不存在没有意义,那么这个数据就是一个异常值,会严重影响模型的性能。
# 添加房屋均价
df = lianjia_df.copy()
df['PerPrice'] = round(lianjia_df['Price']/lianjia_df['Size'], 2)
# 重新摆放列位置
columns = ['Region', 'District', 'Garden', 'Layout', 'Floor', 'Year', 'Size', 'Elevator', 'Direction', 'Renovation', 'PerPrice', 'Price']
df = pd.DataFrame(df, columns =columns)
df.head()
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()
# 画三个图,长,高figsize = (20, 15)
f, [ax1, ax2, ax3] = plt.subplots(3, 1, figsize = (20, 20))
# (每平米单价对比图)
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()
# 画两幅图
f, [ax1,ax2] = plt.subplots(1, 2, figsize=(15, 5))
# 建房时间的分布 kdeplot(核密度估计图)
# 核密度估计(kernel density estimation)是在概率论中用来估计未知的密度函数,属于非参数检验方法之一。
# 通过核密度估计图可以比较直观的看出数据样本本身的分布特征。
sns.distplot(df['Size'], bins=20, ax=ax1, color='r')
sns.kdeplot(df['Size'], shade=False, ax=ax1)
# 建房时间和出售价格的关系
sns.regplot(x='Size', y='Price', data=df, ax=ax2)
plt.show()
得到如下的图:
# 找出异常值 ,此时都是别墅,不在分析范围内,所以移除
df.loc[df['Size']< 10]
得到如下结果:
# 这条数据 1019平,无厅,可能是商品房,所以移除
df.loc[df['Size'] > 1000]
得到的结果如下:
去除异常值后我们重新画图:
# 去除异常值
df = df[(df['Layout'] != '叠拼别墅') & (df['Size'] < 1000)]
# 重新画图 图中无明显异常值
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()
得到的结果是:
f, ax1 = plt.subplots(figsize = (20, 20))
sns.countplot(y = 'Layout', data = df, ax = ax1)
ax1.set_title('房屋户型',fontsize=20)
ax1.set_xlabel('数量')
ax1.set_ylabel('户型')
plt.show()
得到的结果是:
df['Renovation'].value_counts()
# 去掉错误数据“南北”,去除 Renovation 中的异常值,
df['Renovation'] = df.loc[(df['Renovation'] != '南北'), 'Renovation']
# 画出分类直方图
f, [ax1, ax2, ax3] = plt.subplots(3, 1, figsize =(10, 15))
sns.countplot(df['Renovation'], ax = ax1)
sns.barplot(x = 'Renovation', y = 'Price', data = df, palette = "Set3", ax = ax2)
sns.boxplot(x = 'Renovation', y = 'Price', data = df, ax = ax3)
plt.show()
# 查询是否有缺失值,
misn = len(df.loc[(df['Elevator'].isnull()), 'Elevator'])
print('缺失值的数量是:', misn)
df['Elevator'].value_counts()
# 如果有错误值,需要移除,
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('是否有电梯')
ax3.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()
得到的图如下:
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()