前言

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

  1. 熟练使用numpy pandas 进行数据清洗和预处理;
  2. 熟练使用pandas进行数据统计;
  3. 熟练使用matplotlib seaborn进行数据可视化;
  4. 了解机器学习常用算法,并能够做一个项目。

我将1-3归为Phase1,也就是这篇文章的主体内容。本篇以模仿为主,俗话说输出是最好的学习方式。希望通过这篇文章可以增加自己对Python基础的熟练程度,内化常规的数据分析思路。

分析思路

分析目标:查看北京二手居民住房的分布价格情况Part 1- 数据读取和预处理
理解变量、数据选取、重复值缺失值处理Part 2 - 北京市房源分布
数量、单价、总价Part 3 - 各城区房源分布Part 4 - 各城区房价分布
单价分布、总价分布、高价Top15小区、低价Top15小区Part 5 - 各城区房源面积分布
全市平均面积分布、各城区平均面积分布、各城区总面积分布Part 6 - 房价与房源特性的关系
房价与户型、楼层、朝向、建筑年代的关系

Part 1 - 数据读取和预处理

  1. 获取数据

本篇使用参考资料文章3的数据:https://pan.baidu.com/s/1_n3TkvESgOXfl5TUoqlk7w。

#导入常用包
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns#导入数据
filepath='./lianjia_beijing.csv'
rawdata=pd.read_csv(filepath,header=0)#查看数据
rawdata.head()

可以看到一共有12个变量,包括:

  • Direction: 房屋朝向;
  • Region/District/Gadern: 城区/街道/小区地址或者名称
  • Id: 链家编码
  • Elevator: 楼是否有电梯
  • Floor:楼层
  • Layout: 房屋户型
  • Renovation: 装修情况
  • Size: 房屋大小,单位平米
  • Year: 房屋建筑年代
  • Price: 房屋总价

2. 查看缺失值以及变量类型

rawdata.info()

可以看到-

  • 变量类型都符合预期,其中数值型变量的类型均为int64,不需要进行进一步处理;
  • 只有Elevator有缺失值,并且缺失数量并不少,之后需要进一步处理。

3. 查看重复值

在查看重复值时,发现真的有,但是打印出来查看的时候没有发现真的重复;没有找到原因,但是还是将重复的删掉了。

4. 处理缺失值

发现有6种情况:‘NaN’'无电梯', '有电梯', '毛坯', '精装', '简装';因为数据抓取时有串行,导致数据不正确,所以删除 '毛坯', '精装', '简装';同时考虑楼房6层以下的无电梯,高层有电梯对缺失值进行填补,不过考虑Floor显示的只是此房源楼层而不是小区楼层,可能有误差。分析结果应该谨慎参考。

#缺失值处理
df.loc[(df['Elevator'].isnull())&(df['Floor']>6),'Elevator']='有电梯'
df.loc[(df['Elevator'].isnull())&(df['Floor']<=6),'Elevator']='无电梯'
del_row=df[(df['Elevator'] == '毛坯')|(df['Elevator'] == '简装')|(df['Elevator'] == '精装')].index.tolist()
len(del_row)
df=df.drop(del_row).reset_index(drop=True)
df.info()

5. 查看数据的一般描述统计值

df.describe()

可以看到:

  • 楼层分布在1到57层,75%集中在20层以下;
  • Id没有实际意义,可以去掉;
  • 每套房子总价在60W-6000W之间;75%价格小于710万,所以6000W有些异常;
  • 房子面积在15平-1019平之间;75%的面积小于118平,所以最高面积1019平也有些异常;
  • 房子建造年代从1950到2017年。

6. 异常值处理

考虑要分析普通居民住宅,所以具体查看房屋面积进行处理。

#查看区域面积分布
f, ax1=plt.subplots(1,figsize=(15,10))
sns.boxplot(x="Region",y="Size",data=df,ax=ax1)
ax1.set_title("北京各大区二手房面积分布")
ax1.set_xlabel('区域')
ax1.set_ylabel('二手房面积')
plt.xticks(fontsize=9)
plt.show()

可以看到:

  • 怀柔的房屋面积分布范围明显比其他城区广,具体查看数据,的确是建筑的居民楼面积较大。考虑其地理位置,数据情况和实际相符;
  • 面积小于20的查看了,无明显异常;
  • 面积大于800的几个房源很明显。单独查看发现其中“新华联科技大厦”1房间0卫有1019平,明显不是居民住宅,需要删除;同时考虑“X房间0卫”也看起来也不像是居民住宅;

进一步查看,户型分布,从逻辑上看是否有需要删除的异常值。发现有“X房间0卫”和“X室0厅”有很多;分布查看数据后发现“X室0厅”符合居民住宅情况,最后决定删除所有的“X房间0卫”。

#户型面积分布
f, ax1=plt.subplots(1,figsize=(10,10))
sns.boxplot(y="Layout",x="Size",data=df,ax=ax1)
ax1.set_title("北京二手房户型面积分布")
ax1.set_xlabel('户型')
ax1.set_ylabel('二手房面积')
plt.xticks(fontsize=9)
plt.show()

#找到需要删除的行
del_list=df.loc[(df['Layout']=='5房间0卫')|(df['Layout']=='3房间0卫')|(df['Layout']=='2房间0卫')|(df['Layout']=='1房间0卫')].index.tolist()
del_list
df=df.drop(del_list) #删除x房间0卫

7. 变量选取

  • 删除变量“Id”因为没有实际意义;
  • 增加每平米单价“PerPrice”便于之后分析;
  • 重新设置变量位置,方便查看。
#选取子集
df=df.drop(['Id'],axis=1).reset_index(drop=True)
# 添加新特征房屋均价
df['PerPrice'] =df['Price']/df['Size']
# 重新摆放列位置
columns = ['Region', 'District', 'Garden', 'Layout', 'Floor', 'Year', 'Size', 'Elevator', 'Direction', 'Renovation', 'PerPrice', 'Price']
df = pd.DataFrame(df, columns = columns)
df.head()

df.describe()

Part 2 - 北京市房源分布

# 北京二手房分布情况
%matplotlib inline
sns.set_style({'font.sans-serif':['simhei','Arial']})
f, [ax1,ax2,ax3] = plt.subplots(3,1, figsize=(15, 5))
sns.distplot(df['Size'], bins=30, ax=ax1, color='r')
sns.kdeplot(df['Size'], shade=True, ax=ax1)
sns.distplot(df['Price'], bins=30, ax=ax2, color='r')
sns.kdeplot(df['Price'], shade=True, ax=ax2)
sns.distplot(df['PerPrice'], bins=30, ax=ax3, color='r')
sns.kdeplot(df['PerPrice'], shade=True, ax=ax3)
plt.show()

  • 房间面积集中在0-200平以内,更大面积的房源面积变化范围大但数量很少;
  • 二手房总价集中在1000W以内;
  • 二手房每平米均价在4W左右最多,但均价的分布明显更加分散从3W-10W的房源数量都不算少。

Part 3 - 各城区房源分布

# 对二手房区域分组对比二手房数量
df_house_count = df.groupby('Region')['Price'].count().sort_values(ascending=False).to_frame().reset_index()#正确显示中文以及负号
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
sns.set_style({'font.sans-serif':['SimHei','Arial']})f,ax=plt.subplots(1,1,figsize=(20,10))
sns.barplot(x='Region', y='Price',palette="Greens_d", data=df_house_count)
ax.set_title('北京各大区二手房数量对比')
ax.set_xlabel('区域')
ax.set_ylabel('数量')
plt.xticks(fontsize=9)#减小字体以免变成方框
plt.show()

  • 丰台、海淀、朝阳和昌平数量相近,在第一梯队;西城和大兴数量相近,在第二梯队;平谷、怀柔和密云数量非常少;

Part 4 - 各城区房价分布

  1. 各区域总价以及每平米均价分布
#各城区房平均总价分布
df_price_mean=df.groupby("Region")["Price"].mean().sort_values(ascending=False).to_frame().reset_index()
f,[ax1,ax2]=plt.subplots(2,1,figsize=(20,15))
sns.barplot(x="Region",y="Price",palette="Blues_d",data=df_price_mean,ax=ax1)
ax1.set_title("北京各大区二手房总价对比")
ax1.set_xlabel('区域')
ax1.set_ylabel('总价(区域均值)')sns.boxplot(x="Region",y="Price",data=df,ax=ax2)
ax2.set_title("北京各大区二手房总价分布")
ax2.set_xlabel('区域')
ax2.set_ylabel('总价')
plt.xticks(fontsize=9)
plt.show()

#各城区房每平米单价分布
df_perprice_mean=df.groupby("Region")["PerPrice"].mean().sort_values(ascending=False).to_frame().reset_index()
f,[ax1,ax2]=plt.subplots(2,1,figsize=(20,15))
sns.barplot(x="Region",y="PerPrice",palette="Blues_d",data=df_perprice_mean,ax=ax1)
ax1.set_title("北京各大区二手房每平米单价对比")
ax1.set_xlabel('区域')
ax1.set_ylabel('每平米单价')sns.boxplot(x="Region",y="PerPrice",palette="Blues_d",data=df,ax=ax2)
ax2.set_title("北京各大区二手房每平米单价分布")
ax2.set_xlabel('区域')
ax2.set_ylabel('每平米单价')
plt.xticks(fontsize=9)
plt.show()

  • 东西城、海淀、怀柔和朝阳的平均每套二手房总价相近,在第一梯队;除怀柔外,每平米单价也保持和总价一样的排名;怀柔的均价并不在第一梯队,结合之前的房屋面积,因为怀柔二手房的房屋面积较大,造成总价较高;
  • 东西城、海淀和朝阳的二手房总价分布也非常接近,怀柔的价格分布范围较广;
  • 平谷、密云、门头沟和房山4个区域的房子总价和单价都很低,尤其是平谷和密云;为什么怀柔的二手房情况要远远好于它们,有待考证。

2. 房价Top15小区

#查看房屋总价最贵的小区
totalp_village = df.groupby(['Garden','Region'])['Price'].mean().sort_values(ascending = False).reset_index().head(15)
totalp_village
#城区分布
Topdis_check=totalp_village.groupby('Region')['Price'].count().sort_values(ascending = False).reset_index()
Topdis_check

#查看单价最贵的小区
Perp_village = df.groupby(['Garden','Region'])['PerPrice'].mean().sort_values(ascending = False).reset_index().head(15)
Perp_village
#对应城区分布
Perdis_check=Perp_village.groupby('Region')['PerPrice'].count().sort_values(ascending = False).reset_index()
Perdis_check

  • Top结果与区域价格分析一致,贵的小区集中在西城东城,如果看总价的话,还有城六区外的顺义和昌平有小区入选。

Part 5 - 各区域房屋面积分布

按照前面对于Size的查看,以区间[0,50)、[50,100)、[100,150)、[150,200)、[200,+∞)为划分标准,将面积划分为Mini small、small、medium、big、huge五个等级,分别对应极小户型、小户型、中等户型、大户型和巨大户型。

df.loc[(df['Size']>=0)&(df['Size']<50),'Size_level']="Mini Small"
df.loc[(df['Size']>=50)&(df['Size']<100),'Size_level']="Small"
df.loc[(df['Size']>=100)&(df['Size']<150),'Size_level']="Mediumn"
df.loc[(df['Size']>=150)&(df['Size']<200),'Size_level']="Big"
df.loc[(df['Size']>=200),'Size_level']="Huge"
df_sizelevel_count=df.groupby('Size_level')['Price'].count().sort_values(ascending=False).to_frame().reset_index()# 对二手房面积分类后对比二手房数量,总价和每平米房价
df_house_count1 = df.groupby('Size_level')['Price'].count().sort_values(ascending=False).to_frame().reset_index()
df_house_mean1 = df.groupby('Size_level')['PerPrice'].mean().sort_values(ascending=False).to_frame().reset_index()f, [ax1,ax2,ax3] = plt.subplots(1,3,figsize=(15,5))sns.barplot(x='Size_level', y='Price', palette="Greens_d", data=df_house_count1, ax=ax1)
ax1.set_title('北京各类别二手房数量对比')
ax1.set_xlabel('类别')
ax1.set_ylabel('数量')
sns.boxplot(x='Size_level', y='Price', data=df, ax=ax2)
ax2.set_title('北京类别二手房房屋总价')
ax2.set_xlabel('类别')
ax2.set_ylabel('房屋总价')
sns.barplot(x='Size_level', y='PerPrice', palette="Blues_d", data=df_house_mean1, ax=ax3)
ax3.set_title('北京各类别二手房每平米单价对比')
ax3.set_xlabel('类别')
ax3.set_ylabel('每平米单价')
plt.show()

  • 市场上最多的二手房面积在[50,100)内,[100,150)次之;
  • 从房屋总价来看,超小户型<小户型<中等户型,并且三类价格比较集中;
  • 从每平米单价来看,超小户型最高,其余几类差别不算太大,结合房屋总价,可能跟供需关系有关,总价低的市场需求量大,而相对供给量较低。

Part 6 - 房价与房源特性的关系

  1. 房价与户型分布

考虑之前的户型非常多,写法不一,根据全部的分布情况,只选取数量大于10套的户型进行可视化查看。因为户型分类较多,没有看到特别明显的和房价的关系。

#房每平米均价/数量和户型
df_layout_count1=df.groupby('Layout')['PerPrice'].count().sort_values(ascending=False).to_frame().reset_index().head(26)
sel_layout=df_layout_count1['Layout'].tolist()
df2=df.loc[df['Layout'].isin(sel_layout)]
df_layout_perprice1=df2.groupby('Layout')['PerPrice'].mean().sort_values(ascending=False).to_frame().reset_index().head(26)
plt.figure(figsize=(15,5))
x=np.arange(df_layout_perprice1.shape[0])
plt.bar(x*3+1, df_layout_perprice1['PerPrice'])
plt.title('房屋户型均价')
plt.xticks(x*3+1.5,df_layout_perprice1['Layout'],fontsize=8)
plt.xlabel('房屋户型')
plt.ylabel('均价')
plt.show()

2. 房价与朝向分布

统计发现朝向的写法非常乱,所以选取朝向套数>100的进行可视化查看。发现房屋朝向与房屋价格并没有什么明显的关系。

#房均价/数量和朝向
sel_direct=df['Direction'].value_counts().to_frame()
sel_direct_list=sel_direct.loc[sel_direct['Direction']>100].index.tolist()
df_direct=df.loc[df['Direction'].isin(sel_direct_list)]
df_direct['Direction'].value_counts()# 对二手房朝向
df_house_count2 = df_direct.groupby('Direction')['Price'].count().sort_values(ascending=False).to_frame().reset_index()
df_house_mean2 = df_direct.groupby('Direction')['PerPrice'].mean().sort_values(ascending=False).to_frame().reset_index()f, [ax1,ax2,ax3] = plt.subplots(3,1,figsize=(10,15))sns.barplot(x='Direction', y='Price', palette="Greens_d", data=df_house_count2, ax=ax1)
ax1.set_title('北京各朝向二手房数量对比')
ax1.set_xlabel('朝向')
ax1.set_ylabel('数量')
sns.boxplot(x='Direction', y='Price', data=df_direct, ax=ax2)
ax2.set_title('北京各朝向二手房房屋总价')
ax2.set_xlabel('朝向')
ax2.set_ylabel('房屋总价')
sns.barplot(x='Direction', y='PerPrice', palette="Blues_d", data=df_house_mean2, ax=ax3)
ax3.set_title('北京各朝向二手房每平米单价对比')
ax3.set_xlabel('朝向')
ax3.set_ylabel('每平米单价')
plt.show()

3. 房价与装修分布

  • 在售二手房以精装和简装为主;
  • 毛坯房数量虽少,却在每平单价和总价上均超过了精装房。查看毛坯房源分布的区域和面积都很分散,没有明显特征,原因有待考证。
#房均价/数量和装修
df['Renovation'].value_counts()
# 画幅设置
f, [ax1,ax2,ax3] = plt.subplots(1, 3, figsize=(15, 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()

4. 房价与楼层

  • 6层房源最多;
  • 1层、42和57层的每平米单价明显较高;其余层差异不大;
  • 2层、3层的房屋总价分布与每平米单价表现不一致,平均总价明显高于其他楼层。
#房均价/数量和楼层
df['Floor'].value_counts()f, [ax1,ax2,ax3] = plt.subplots(3, 1, figsize=(20, 10))
sns.countplot(df['Floor'], ax=ax1)
sns.barplot(x='Floor', y='PerPrice', data=df, ax=ax2)
sns.boxplot(x='Floor', y='Price', data=df, ax=ax3)
plt.show()

5. 房价与电梯

电梯的数值在前面进行过填充,此处显示有电梯的房源数量和总价都高于没有电梯的,符合常识。但是填充的结果是否正确,也有待考证。

#房均价/数量和有无电梯
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()

6. 房价与建筑年限

y1=df.groupby('Year').Price.mean().reset_index()
y2=df.groupby('Year').PerPrice.count().reset_index()
x=y1.Year
plt.plot(x,y1.Price,label='Total Price')
plt.plot(x,y2.PerPrice,'r--',label='Total Number')
plt.legend(loc='best')
plt.show()

plt.figure(figsize=(15,5))
df.groupby('Year').PerPrice.mean().plot()
plt.title('建筑时间-每平米单价')

#不同城区的建筑情况
plt.figure(figsize=(15,10))
sns.swarmplot(x="Year",y="Region",data=df)
plt.title('建筑时间-数量')
plt.show()

  • 2000-2010年10年间北京大规模增加住宅,房屋总价同时增长,但整体房屋单价下降;结合不同年限各区域的住宅分布,可知这段实际增加了非内城区的其他区域的住宅,所以单价没有增加;
  • 西城的住宅建设开始的最早,1980年之后各大城区才开始建设;建设时间和城区位置相符。

小结

通过分析可以看到,二手房市场的房源数量和房价表现出的北京特征非常明显:

  • 中心城区东西城和学区房海淀朝阳房源多同时房价高;
  • 房源面积集中在50-150平之内,总价均值在500-600万,<50平的房源因为房屋数量少和总价低,反而单价最高;
  • 房屋的建筑时间和北京各区域发展的时间一致;
  • 房价更多与区域位置和面积相关,与户型、装修和电梯等等相关性不明显。

本篇侧重于锻炼python实现数据清洗和可视化的能力,不足之处:

  • 对于变量电梯、朝向、户型等的处理非常粗糙;
  • 分析的问题不够明确,导致分析结论不明确。

参考资料:

  1. 第二篇数据分析项目实战:链家二手房分析
  2. 乐天:Python进行电影数据分析及可视化
  3. 路远:入门Python数据分析最好的实战项目(一)分析篇

小感悟:当目标不同时,即使数据源相同,分析的呈现思路也是完全不一样的:1和2都是对数据有预设问题,带着问题去看数据找到结论;3更突出探索性分析的特点,目标是为了理解完数据之后选取特征建模。

python建筑案例_Python数据分析实战-链家北京二手房价分析相关推荐

  1. 爬虫实战-链家北京房租数据

    爬虫实战-链家北京房租数据 本篇是对 恋习Python 发布的原创文章<北京房租大涨?6个维度,数万条数据帮你揭穿>中涉及的代码部分的解读. < 在复现原文代码时,出现了一些报错,在 ...

  2. python数据分析项目实战—————链家北京租房数据统计分析

    链家北京租房数据分析 1.读取数据 import pandas as pd import matplotlib.pyplot as plt import numpy as npdata_dframe ...

  3. python找房源_python抓取链家房源信息(二)

    试着用scrapy将之前写的抓取链家网信息的重新写了写 然后先是用了第一页的网页作为测试,调试代码,然后发现总是抓取的时候遇见了 类似于这样的问题,并且抓取不到信息 2017-03-28 17:52: ...

  4. 多进程+多线程爬取链家武汉二手房价

    因为数据分析的需要,就写了爬取链家武汉的数据.因为用scrapy框架感觉太慢了,就自己写了个多进程同步执行的代码. 1.数据量:20000+ 2.程序环境:Python3.6--->用的Anac ...

  5. python聚类分析案例_python 聚类分析实战案例:K-means算法(原理源码)

    K-means算法: 关于步骤:参考之前的博客 关于代码与数据:暂时整理代码如下:后期会附上github地址,上传原始数据与代码完整版, 各种聚类算法的对比:参考连接 Kmeans算法的缺陷 1.聚类 ...

  6. python因子分析案例_python数据分析单因子分析

    集中趋势 均值 panda.mean() 分位数 panda.quantile(q) q = 0.25 Q1 = (n+1)0.25 q = 0.5 中位数 Q1 = (n+1)0.5 q = 0.7 ...

  7. Selenium+ChromeDriver爬取链家网二手房价(包括经纬度)信息

    [需求]   爬取青岛市二手房源信息,要求包括房源基本信息.小区名称.总价.单价以及房源的经纬度信息.   根据以上需求,进入青岛市二手房首页,如图1所示,进行页面分析: 图1 [页面分析]   首先 ...

  8. 数据挖掘与数据分析项目链家租房数据(一)数据爬虫

    数据挖掘与数据分析项目链家租房数据(一)数据爬虫 今日无聊将一个过去做的链家数据分析项目弄上来,当时是某面试,三天时间完成,主要是供大家抄代码和分享一下思考点,这一章是爬虫部分. 网站原图 结果截图 ...

  9. 基于python多线程和Scrapy爬取链家网房价成交信息

    文章目录 知识背景 Scrapy- spider 爬虫框架 SQLite数据库 python多线程 爬取流程详解 爬取房价信息 封装数据库类,方便多线程操作 数据库插入操作 构建爬虫爬取数据 基于百度 ...

最新文章

  1. vi 方向键和Backspace键失效问题的解决方法
  2. 跟我一起写操作系统(二)——史上最简单的内核
  3. java中字符串的精确匹配_Java最佳实践–字符串性能和精确字符串匹配
  4. 前端学习(3139):react-hello-react之生命周期组件挂载过程
  5. org.hibernate.MappingException: Could not determine type for: java.util.List, at table: user, for...
  6. 腾讯智慧出行和现代汽车集团创新中心(北京)正式建立创新战略合作伙伴关系
  7. 《软件项目管理(第二版)》第 3 章——项目计划 重点部分总结
  8. RTT的内存管理篇——为什么要进行内存管理?
  9. 捋一捋20201217
  10. 拼多多年货节上线,“百亿补贴”加码iPhone 12等产品
  11. ios php mysql实例_如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1
  12. 基于图像界面工具postman进行测试
  13. NYOJ 588 Money
  14. html输入框素材,html文本框代码
  15. 电力系统服务器是什么,什么是电网调度?
  16. idea 2021 IDEA的Persistence 窗口 查看ERD关系图
  17. 创造一颗属于你的星球
  18. Ubuntu及window的配置 java变量和快捷键
  19. 2018秋c语言程序设计考试答案,2018年自学考试《C语言程序设计》模拟试题【四篇】...
  20. 不小心点了计算机一键还原怎么操作,电脑按了一键还原系统怎么办

热门文章

  1. 爬取Github Web API 并存入Mysql数据库
  2. java controller json_springMVC的controller层接收前端json数据
  3. 中富之命能有多少钱_邯郸白铁风管工每天工资多少钱?白铁风管价格多少钱你能接受?...
  4. execel公式 java工具_PAP-快速开发框架:JAVA 计算器 自定义公式 解决EXCEL计算公式问题...
  5. 主成分分析法案例_因子分析案例及操作解析
  6. python turtle颜色rgb_turtle绘图总结
  7. obs噪音抑制调多少合适_TVS瞬态抑制二极管的特性及应用
  8. tensorflow中创建多个计算图(Graph)
  9. 数字图像处理总结(冈萨雷斯版)
  10. Python文件拷贝函数