首页 >> 大全

pandas杭州市出租房分析

2023-06-17 大全 77 作者:考证青年

前言:很早之前学了爬虫,但是一直没有对爬虫数据进行分析过,最近爬了2019年2月份的58同城杭州租房信息,希望分析一下杭州房租情况,租金分布是怎么样的,哪里的性价比最好。

数据来源

数据是集采于58同城的租房信息(代码见)

数据如图1所示,包含字段:title, , area, , , , , price

图2是58租房页面信息分别对应表里的字段

由于爬数据的时候没有对数据进行过清洗和特别的处理,所以可以看到表里的字段里面的值里面有很多空格,另外如户型和面积的信息被提取在同一个字段里面了。接下里需要对数据进行一下清洗。

数据预处理

数据清洗

对title,,,等字段进行解析,冗余信息处理(eg:空格 m2),从而得到租赁类型(eg:单间和整租),面积,商圈,公寓,经纪公司。

#数据清洗
info['type']=info['title'].str.split('|',expand=True)[0].str.replace('[\n\s+]','')
info['m_area']=info['room_type'].str.replace('\s+|㎡','#').str.split('#',expand=True)[1].astype(float)
info['m_room_type']=info['room_type'].str.replace('\s+','#').str.split('#',expand=True)[0]
info['m_room_type']=info.m_room_type.str.replace('两','2')
info['send_time']=info['send_time'].str.replace('[\n\s+]','')
info['m_rent_origin']=info['rent_origin'].str.replace('[\n\s+]','')
info['m_department']=info['address'].str.split(';',expand=True)[1]
info['m_address']=info['address'].str.split(';',expand=True)[0]
info['price_int']=info[info['price']!='面议']['price'].astype(float)
info['fee_avg_square']=info.apply(lambda info: info['price_int'] / info['m_area'], axis=1)

地址解析

由于没有爬虫的数据里面没有区域信息如西湖区,江干区,区域又是重要的分析维度,因此调用了的接口根据公寓名获得具体的经纬度,再根据经纬度获取区域信息

# 地址解析 根据地址名称返回经纬度
import requests 
def geocode(address): parameters = {'address': address, 'key': 'XXXXXXX'} ## key 高德api注册,申请一个应用可以获得base = 'http://restapi.amap.com/v3/geocode/geo'headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36','Cookie': 'id58=c5/njVpymhR0X0thDRuHAg==; commontopbar_new_city_info=79%7C%E6%9D%AD%E5%B7%9E%7Chz; 58tj_uuid=763a5398-da95-4db2-9a54-ba7f4171f17c; new_uv=1; wmda_uuid=80797b44db9604b45dfbf4807417e58f; wmda_new_uuid=1; wmda_visited_projects=%3B2385390625025; commontopbar_ipcity=hz%7C%E6%9D%AD%E5%B7%9E%7C0; commontopbar_myfeet_tooltip=end; als=0; xxzl_deviceid=d7wGUAUqik8MomhIMsEH98iyUnHRBDyrCJYsasv1uq9biXZ%2F%2Bxav%2BhZr%2FQQmLjYF; wmda_session_id_2385390625025=1517477544470-6db397e1-9d59-3e58'#'Host': 'cdata.58.com',#'Referer': 'http://webim.58.com/index?p=rb'}response = requests.get(base, parameters,headers=headers)answer = response.json()print(address)print(answer)return answer['geocodes'][0]['location']#print(address + "的经纬度:", answer['geocodes'][0]['location'])

info['department1']='杭州市'+info['m_department']
info['lngandlat']=info[info['department1'].notnull()].department1.apply(geocode)

def googlelocatebyLatLng(lat, lng, pois=0):'''根据经纬度查询地址'''items = {'location': str(lng) + ',' + str(lat), 'key': 'XXXXXX'}headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36','Cookie': 'id58=c5/njVpymhR0X0thDRuHAg==; commontopbar_new_city_info=79%7C%E6%9D%AD%E5%B7%9E%7Chz; 58tj_uuid=763a5398-da95-4db2-9a54-ba7f4171f17c; new_uv=1; wmda_uuid=80797b44db9604b45dfbf4807417e58f; wmda_new_uuid=1; wmda_visited_projects=%3B2385390625025; commontopbar_ipcity=hz%7C%E6%9D%AD%E5%B7%9E%7C0; commontopbar_myfeet_tooltip=end; als=0; xxzl_deviceid=d7wGUAUqik8MomhIMsEH98iyUnHRBDyrCJYsasv1uq9biXZ%2F%2Bxav%2BhZr%2FQQmLjYF; wmda_session_id_2385390625025=1517477544470-6db397e1-9d59-3e58'#'Host': 'cdata.58.com',#'Referer': 'http://webim.58.com/index?p=rb'}res = requests.get('http://restapi.amap.com/v3/geocode/regeo', params=items,headers=headers)result = res.json()#print('--------------------------------------------')#result = result['result']['formatted_address'] + ',' + result['result']['sematic_description']result = result['regeocode']['addressComponent']['district']print(result)return result
info['lng']=info.lngandlat.str.split(',',expand=True)[0]
info['lat']=info.lngandlat.str.split(',',expand=True)[1]
info['district']=info[info['lngandlat'].notnull()].apply(lambda info:googlelocatebyLatLng(info['lat'],info['lng']),axis=1) #axis = 1,就会把一行数据作为Series的数据结构传入给自己实现的函数中,我们在函数中实现对Series不同属性之间的计算,返回一个结果

查看数据基本情况

()

从上图可以发现字段又100多条记录缺失,因此删除这些缺失值的记录。

缺失值处理

info1=info[info.department1.notnull()][['title','type','m_area','m_room_type','m_rent_origin','m_department','m_address','price_int','fee_avg_square','district','lngandlat']]

异常值检测和处理

info1.()

从上面可以看到面积的最大值有800,租金最大有,明显是异常值,下面用箱型图定位一下面积和租金的字段的异常值范围

##  
import matplotlib.pyplot as plt #导入图像库
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号
% matplotlib inline
import numpy as np
Percentile = np.percentile(info1['m_area'],[0,25,50,75,100])
IQR = Percentile[3] - Percentile[1]
UpLimit = Percentile[3]+IQR*1.5
DownLimit = Percentile[1]-IQR*1.5
print('上界:',UpLimit,'下界:',DownLimit)import matplotlib.pyplot as plt #导入图像库
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号f,ax=plt.subplots(figsize=(10,8))
sns.boxplot(data=info1[['m_area']])plt.show()

上界: 123.0 下界: -45.0

同理租金

上界: 4650.0 下界: -550.0

根据箱型图以及实际情况,将面积大于300租金大于20000视为异常将其剔除。

info2=info1[(info1.m_area<=300)&(info1.price_int<=20000)]

另外看了下房屋户型类型发现有9卫9室,0卫等异常的户型,也将其剔除。

info3=info2[~info2['m_room_type'].str.contains(r'.*(0卫|9卫).*')]

通过以上一系列处理最终得到3665条数据。

数据分析及可视化

房源租赁类型分布情况

导人画图的相关包

import matplotlib.pyplot as plt #导入图像库
import seaborn as sns
plt.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus'] = False #用来正常显示负号import seaborn as sns
% matplotlib inline
sns.set(context='notebook',font='simhei',style='darkgrid')info3.type.value_counts().plot(kind='pie',autopct='%3.2f %%')
plt.title('租赁类型分布')
plt.xlabel('租赁类型')
plt.ylabel('房源数量')
plt.legend()

可以发现合租房源略多于整租房源。

房源的区域分布

ax=info3.groupby('district').type.count().sort_values(ascending=False).plot(kind='bar',figsize=(16,6))
district_r=info3.groupby('district').type.count().sort_values(ascending=False).cumsum()/info3.groupby('district').type.count().sort_values(ascending=False).cumsum().max()
ax2 = ax.twinx()
district_r.plot()
ax.set_xlabel('区域')
ax.set_ylabel('房源数量')
ax2.set_yticks(np.arange(0,1.1,0.1))
plt.title('房源的区域分布')

杭州市现有10个行政区,其中70%房源主要集中在江干区,西湖区,拱墅区,萧山。比较神奇的是萧山比滨江区多,且在前3,可能是由萧山已发展起来,又与滨江区接壤,萧山相对滨江租金便宜,因此招租的多。

房源的户型分布情况

 import re
def substr_room(s):room=re.findall(r'[0-9]室',s)return room[0]info3['room']=info3.m_room_type.apply(substr_room)
ax=info3.groupby('room').type.count().sort_values(ascending=False).plot(kind='bar',figsize=(16,6))
room_type_r=info3.groupby('room').type.count().sort_values(ascending=False).cumsum()/info3.groupby('room').type.count().sort_values(ascending=False).cumsum().max()
ax2 = ax.twinx()
room_type_r.plot()
ax.set_xlabel('户型')
ax.set_ylabel('房源数量')
ax2.set_yticks(np.arange(0,1.1,0.1))
plt.title('房源的户型分布')

一半多的房型是3室,现在的房屋户型设计基本都是3室,和实际租房情况相符。

房源的面积分布情况

#将房间面积按区间分类
def area_range(an):if an<=10:area_range = '5-10平'elif an>10 and an<=20:area_range = '10-20平'elif an>20 and an<=30:area_range = '20-30平'elif an>30 and an<=40:area_range = '30-40平'elif an>40 and an<=50:area_range = '40-50平'else:area_range = '50平以上'return area_rangeinfo3['area_range']=info.m_area.apply(area_range)
#画饼状图
labels = info3.area_range.value_counts().index
fracs = info3.area_range.value_counts().valuesfig = plt.figure(figsize=(10,6))
plt.axes(aspect=1)
plt.pie(x=fracs, labels=labels, autopct='%3.2f %%',shadow=False, labeldistance=1.1, startangle=60, pctdistance=0.6)
plt.show

10-20平米的房间最多,占总房源的41.31%,20-30平米的占18.91%,可选范围还是比较广的。

总体租金分布情况

fig = plt.figure(figsize = (20,7))
plt.hist(info3['price_int'], bins=15, rwidth=0.95, alpha=0.7)
plt.title('总体租金分布情况')
plt.xlabel('元/月')
plt.ylabel('频率')
plt.xticks(range(500,20000,500))

杭州市的房租呈长尾偏态,大多数租金集中在1500~2500之间。

不同区域的租价分布情况

f,ax=plt.subplots(figsize=(12,8))
sns.boxplot(x='district',y="price_int",data=info3[info3.type=='整租'])
plt.title('不同区域的租金分布(整租)')
plt.xlabel('区域')
plt.ylabel('租金')
plt.show()

f,ax=plt.subplots(figsize=(12,8))
sns.boxplot(x='district',y="price_int",data=info3[info3.type=='单间'])
plt.title('不同区域的租金分布(单间)')
plt.xlabel('区域')
plt.ylabel('租金')
plt.show()

可以发现各区域合租的租金相对于整租的租金相对集中,整租租金相对分散。

看单间出租图可以看出,滨江区、上城区的租金中位数最高,将近2000/月。余杭区和萧山区租金最低。

f,ax=plt.subplots(figsize=(12,8))
sns.boxplot(x='m_room_type',y="price_int",data=info3[info3.type=='单间'])
plt.title('不同房型的租金分布(单间)')
plt.xlabel('房型')
plt.ylabel('租金')
plt.show()

就单间租金的话,主卧的价格相对高些,2室的主卧相比于3室的主卧又高些。

租金和面积的关系

plt.figure(figsize=(20,6))
sns.regplot(x='m_area', y='price_int', data=info3)
plt.xlabel('面积')
plt.ylabel('租金')
plt.show()

由图中可以看出,随着面积的增长,租金也在上升,大部分房源的面积在100平米以内,租金在一万块以内。

房源分类

本文用聚类分析把这些房源分类,采用常用的K-means聚类算法,通过计算离差平方和来进行分类。聚类原则:组内差距要小,组间差距要大。我们用面积和租金这两个变量对房源进行分类,通过SSE(sum of the ,误差平方和)来确定分类K值。

#############K-means-房源聚类############
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
ss = StandardScaler()#from sklearn import datasets
import numpy as np
X = info3[['m_area','price_int']] ##表示我们只取特征空间中的后两个维度X  = ss.fit_transform(X )origin_data = ss.inverse_transform(X)
# '利用SSE选择k'
SSE = []  # 存放每次结果的误差平方和
for k in range(1, 15):estimator = KMeans(n_clusters=k)  # 构造聚类器estimator.fit(X )SSE.append(estimator.inertia_)
X = range(1, 15)
plt.xlabel('k')
plt.ylabel('SSE')
plt.plot(X, SSE, 'o-')
plt.show()

从图中可以看到,当K=4时,明显曲线下降速度变缓,这说明我们将房源分成4类会比较合适。因此确定这里K=4。

下面进行K-means聚类

estimator = KMeans(n_clusters=4)#构造聚类器
estimator.fit(X)#聚类
label_pred = estimator.labels_ #获取聚类标签#绘制k-means结果
x0 = origin_data[label_pred==0]
x1 = origin_data[label_pred == 1]
x2 = origin_data[label_pred == 2]
x3 = origin_data[label_pred == 3]plt.scatter(x0[:,0], x0[:,1], c = "red", marker='o', label='label0')
plt.scatter(x1[:,0], x1[:,1], c = "green", marker='*', label='label1')
plt.scatter(x2[:,0], x2[:,1], c = "blue", marker='+', label='label2')
plt.scatter(x3[:,0], x3[:,1], c = "yellow", marker='o', label='label3')plt.xlabel('面积')
plt.ylabel('租金')
plt.legend(loc=2)
info3['label']=''
info3['label'][label_pred==0]=0
info3['label'][label_pred==1]=1
info3['label'][label_pred==2]=2
info3['label'][label_pred==3]=3
pd.pivot_table(info3,values=['price_int','m_area'],columns='label',aggfunc='mean')

结果:

info3.label.()

各类中的平均面积,平均租金

pd.(info3,=[‘’,‘’],=‘label’,=‘mean’)

各类在各区域的分布

pd.(info3,=[‘’],index=‘’,=‘label’,=‘count’)

就分类的结果选取了 数据,调用高德api画热力图,图如下:

分类分析如下:

(1)为大户型,平均面积176平米,月租1w以上,月租较高,主要是因为靠近1号,2号,4号地铁口和附近中心区域,交通便利。

(2)介于中型至大型户型,平均面积110平,月租均价4千性价比较高,主要位于滨江区和江干区,但是房源不算多。

(3)为中户型,平均面积68平米,月租均价42元/平米,主要位于余杭区,萧山区,江干区位置更郊区,因此月租低,房源数量多。

(4)为小户型,属于单间出租的多,房源数量上最多,平均面积20平米,月租平均1500,区域分布最广。

结论

看了这么多数据,发现租单间是王道了,房源相对充足,价格也合适。就区域来说,滨江区的租金还是相对贵些,而萧山区性价比高,而两区域接壤,在滨江上班的可以考虑在萧山租房。

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了