python对杭州二手房数据分析
该数据集来自网络公开数据,python语言,在数据分析方面,作为一柄利器,涵盖了“数据获取→数据处理→数据分析→数据可视化”这个流程中每个环节。
环境搭建:
环境:win10+Anaconda +jupyter Notebook
库:Numpy,pandas,matplotlib,seaborn ,missingno,各种包的管理和安装主要利用conda和pip。
数据集:杭州二手房信息样本
探索问题:
要探索的问题有:
1、二手房区域位置特点
2、总价等差间距中房数占比、总价在各区域中的平均值
3、单价等差间距房数占比、单价在各区域的平均值
4、看房时间可视化
6、关注度特点分析
7、楼层高低分析
8、户型结构分析
9、建筑类型
10、朝向分析
11、建筑结构
12、是否有电梯分析
13、用途分析
14、核心卖点词云分析
# 导入需要的数据库
import pandas as pd
import numpy as np
import seaborn as sns
sns.set()
import matplotlib.pyplot as plt
# 设置配置输出高清矢量图:
%config InlineBackend.figure_format = 'svg'
%matplotlib inline
# 使用pandas进行数据读入和分析:
house = pd.read_csv("C:/Users/EVILLIFES/Desktop/接单/Secondhand_house.csv",encoding='gbk')
# 输出主要信息:
house.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 8121 entries, 0 to 8120
Data columns (total 45 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 序号 8121 non-null int64
1 小区名称 8121 non-null object
2 区域位置 8121 non-null object
3 经度 8121 non-null object
4 纬度 8121 non-null object
5 总价 8121 non-null object
6 单价 8121 non-null object
7 看房时间 8121 non-null object
8 链家编号 8121 non-null object
9 关注度 8121 non-null object
10 房屋户型 8119 non-null object
11 所在楼层 8121 non-null object
12 建筑面积 8121 non-null object
13 户型结构 7762 non-null object
14 套内面积 8119 non-null object
15 建筑类型 7762 non-null object
16 房屋朝向 8121 non-null object
17 建筑结构 8119 non-null object
18 装修情况 8119 non-null object
19 梯户比例 7762 non-null object
20 配备电梯 7762 non-null object
21 挂牌时间 8121 non-null object
22 交易权属 8121 non-null object
23 上次交易 8121 non-null object
24 房屋用途 8121 non-null object
25 房屋年限 8121 non-null object
26 产权所属 8121 non-null object
27 抵押信息 8121 non-null object
28 房本备件 8121 non-null object
29 房源核验统一编码 8121 non-null object
30 查询房管备案记录 7744 non-null object
31 核心卖点 7747 non-null object
32 小区介绍 5199 non-null object
33 周边配套 4958 non-null object
34 税费解析 821 non-null object
35 用水类型 1248 non-null object
36 用电类型 1248 non-null object
37 燃气价格 384 non-null object
38 户型介绍 2390 non-null object
39 适宜人群 1436 non-null object
40 装修描述 620 non-null object
41 售房详情 354 non-null object
42 交通出行 200 non-null object
43 别墅类型 358 non-null object
44 权属抵押 21 non-null object
dtypes: int64(1), object(44)
memory usage: 2.8+ MB
# 获得行数和列数
rows = len(house)
columns = len(house.columns)
print(rows,columns)
# 输出列的数据类型
columns_type = house.dtypes
columns_type
8121 45
序号 int64
小区名称 object
区域位置 object
经度 object
纬度 object
总价 object
单价 object
看房时间 object
链家编号 object
关注度 object
房屋户型 object
所在楼层 object
建筑面积 object
户型结构 object
套内面积 object
建筑类型 object
房屋朝向 object
建筑结构 object
装修情况 object
梯户比例 object
配备电梯 object
挂牌时间 object
交易权属 object
上次交易 object
房屋用途 object
房屋年限 object
产权所属 object
抵押信息 object
房本备件 object
房源核验统一编码 object
查询房管备案记录 object
核心卖点 object
小区介绍 object
周边配套 object
税费解析 object
用水类型 object
用电类型 object
燃气价格 object
户型介绍 object
适宜人群 object
装修描述 object
售房详情 object
交通出行 object
别墅类型 object
权属抵押 object
dtype: object
# 为了显示中文
from pylab import mpl
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
# 通过上述info信息我们发现有数据的缺失值,在此我们统计一下缺失情况:
missing_values = house.isnull().sum()
print(missing_values)
# 通过可视化展现为:
import missingno as msno
msno.matrix(house,figsize = (15,5), labels=True)
序号 0
小区名称 0
区域位置 0
经度 0
纬度 0
总价 0
单价 0
看房时间 0
链家编号 0
关注度 0
房屋户型 2
所在楼层 0
建筑面积 0
户型结构 359
套内面积 2
建筑类型 359
房屋朝向 0
建筑结构 2
装修情况 2
梯户比例 359
配备电梯 359
挂牌时间 0
交易权属 0
上次交易 0
房屋用途 0
房屋年限 0
产权所属 0
抵押信息 0
房本备件 0
房源核验统一编码 0
查询房管备案记录 377
核心卖点 374
小区介绍 2922
周边配套 3163
税费解析 7300
用水类型 6873
用电类型 6873
燃气价格 7737
户型介绍 5731
适宜人群 6685
装修描述 7501
售房详情 7767
交通出行 7921
别墅类型 7763
权属抵押 8100
dtype: int64
<Axes: >
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BpE9p5oJ-1684846070283)(output_5_2.svg)]
msno.bar(house,figsize = (15,5)) # 条形图显示
<Axes: >
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WXSYTvWn-1684846070285)(output_6_1.svg)]
数据清洗:
这一步的数据处理,主要是我们在上一步骤中发现的数据集问题:缺失值问题。实际业务中,数据清洗,往往比这麻烦的多,是一项复杂且繁琐的工作(用过excel清洗数据的都知道~),在网上看到,有人说一个分析项目80%的时间都是在清洗数据数据,不无道理。清洗的目的有两个,第一是通过清洗让数据可用。第二是让数据变的更适合进行后续的分析工作。总的说来,一份“脏”数据要清晰,一份“干净”的数据也要清洗。
““脏”数据需要清洗,这是众所周知的。但“干净”的数据也要清洗?这听起来很让人疑惑,其实我个人觉得更准确的表达是,这属于特征工程中的特征构造,构造出我们需要的特征。利于下一步分析。
就拿数据分析钟我们常见的处理日期变量问题来说,有时需要我们在日期变量中,提取对应的星期数,构造为以星期的方式来表述日期,有时又需要我们在日期变量中,提取月份,构造为以月份的方式展现日期,又或者把连续型数值数据离散化,构造分类区间等等。这些处理方式,在ML中被叫做特征工程,但本质上就是数据清洗。
缺失值处理中,我们一般会删除缺失值。pandas模块中,提供了将包含NaN值的行删除的方法dropna(),但其实处理缺失值最好的思路是“用最接近的数据替换它”
对于数值型数据,可用该列的数据的均值或者中位数进行替换,对于分类型数据,可利用该列数据的出现频数最多的数据(众数)来填充。
实在处理不了的空值,可以暂时先放着,不必着急删除。因为在后续的情况可能会出现:后续运算可以跳过该空值进行。
通过对空值数据的分析我们发现:【房屋户型、户型结构、套内面积、建筑类型、建筑结构、装修情况、梯户比例、配备电梯、查询房管备案记录、核心卖点、小区介绍、周边配套、税费解析、用水类型、用电类型、燃气价格、户型介绍、适宜人群、装修描述、售房详情、交通出行、别墅类型、权属抵押】有却失值。
对于我们需要的数据有影响的有【户型结构(缺359)、建筑类型(缺359)、建筑结构(缺2)、配备电梯(缺359)、核心卖点(缺374)、别墅类型(缺7763)】。
我们发现在这些数据中,并没有像数值一样的列存在,所有,我们可以对缺失值跳过。
# 对总价和单价列进行数值类型转换:
price = pd.to_numeric(house['总价'], errors='coerce',).fillna(0)
unit_price = pd.to_numeric(house['单价'], errors='coerce',).fillna(0)
print(price)
print(unit_price)
0 930.0
1 765.0
2 225.0
3 148.0
4 130.0
...
8116 205.0
8117 570.0
8118 440.0
8119 242.0
8120 325.0
Name: 总价, Length: 8121, dtype: float64
0 69053.0
1 55423.0
2 34611.0
3 31835.0
4 26461.0
...
8116 30308.0
8117 36562.0
8118 48993.0
8119 32903.0
8120 44260.0
Name: 单价, Length: 8121, dtype: float64
# 总价分析:
price.describe()
count 8121.000000
mean 429.089820
std 368.176619
min 0.000000
25% 210.000000
50% 320.000000
75% 545.000000
max 6500.000000
Name: 总价, dtype: float64
# 单价分析:
unit_price.describe()
count 8121.000000
mean 40310.525305
std 18436.762039
min 0.000000
25% 26552.000000
50% 37487.000000
75% 48544.000000
max 128968.000000
Name: 单价, dtype: float64
# 对建筑结构一列的数据填补
# 首先查看当前占比
house['建筑结构'].value_counts()
钢混结构 5612
砖混结构 1015
混合结构 851
框架结构 478
钢结构 91
未知结构 44
砖木结构 27
建筑结构 1
Name: 建筑结构, dtype: int64
# 发现钢混结构占比最大,所以我们用钢混结构来补充缺失值
house.fillna({
'建筑结构':'钢混结构'},inplace=True)
structure = house['建筑结构']
# 查看是否还存在缺失值
structure.isnull().sum()
0
对其他缺值的处理:
pandas模块中,提供了将包含NaN值的行删除的方法dropna()
数据可视化
pandas.pivot_table函数中包含四个主要的变量,以及一些可选择使用的参数。四个主要的变量分别是数据源data,行索引index,列columns,和数值values。可选择使用的参数包括数值的汇总方式,NaN值的处理方式,以及是否显示汇总行数据等。
在可视化分析方面,会涉及到python常用的绘图库:matplotlib和seaborn,网上已经有非常多的使用指南,这里就不多说了,以后有时间,也会做一些总结。
# 手动区间划分
# 总价占比:
f1 = [0,0,0,0,0,0,0]
y1 = ['>6000','<=6000','<=5000','<=4000','<=3000','<=2000','<=1000']
for i in price:
if i<=1000.0:
f1[0]+=1
elif i<=2000.0:
f1[1]+=1
elif i<=3000.0:
f1[2]+=1
elif i<=4000.0:
f1[3]+=1
elif i<=5000.0:
f1[4]+=1
elif i<=6000.0:
f1[5]+=1
else:
f1[6]+=1
print(f1)
plt.figure(figsize = (10,5))
plt.subplot(121) # 第一个子图
plt.title("总价占比图")
plt.plot(y1,f1)
# 单价占比:
f2 = [0,0,0,0,0,0]
y2 = ['>50000','<=50000','<=40000','<=30000','<=20000','<=10000']
for i in price:
if i<=10000.0:
f2[0]+=1
elif i<=20000.0:
f2[1]+=1
elif i<=30000.0:
f2[2]+=1
elif i<=40000.0:
f2[3]+=1
elif i<=50000.0:
f2[4]+=1
else:
f2[5]+=1
print(f2)
plt.figure(figsize = (10,5))
plt.subplot(122) # 第一个子图
plt.title("单价占比图")
plt.plot(y2,f2)
[7691, 373, 44, 8, 3, 1, 1]
[8121, 0, 0, 0, 0, 0]
[<matplotlib.lines.Line2D at 0x283bed15c30>]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-K3VTAEja-1684846070287)(output_16_2.svg)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yJItnJa4-1684846070288)(output_16_3.svg)]
# 使用工具进行区间划分
house["总价分布"]=pd.cut(price,5)#将年龄列的数值划分为5等分
price_info = house["总价分布"].value_counts(sort=False)#查看每个分组有多少人数
price_info.plot(label='数量',title='对应区间划分内房屋数量',figsize=(11,5))
plt.show()
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yXMFdtPl-1684846070289)(output_17_0.svg)]
# 区域单价分析
f3 = house['区域位置'].value_counts(ascending=True)
print(f3)
plt.figure(figsize= (25 ,5))#创建画布
plt.xticks(rotation = 90) # 横坐标
plt.plot(f3, linewidth=3, marker='o',
markerfacecolor='blue', markersize=5)
plt.title('区域房数统计')
plt.show()
区域位置 1
富阳 1
拱墅-笕桥 22
拱墅-天水 24
拱墅-德胜东 24
拱墅-体育场路 28
拱墅-三里亭 33
拱墅-丝绸城 34
拱墅-和平 39
富阳-江南新城 42
拱墅-武林 43
拱墅-万达广场 50
拱墅-众安桥 57
拱墅-德胜 74
拱墅-潮鸣 85
拱墅-长庆 86
拱墅-三墩 87
富阳-富阳 91
富阳-鹿山新城 95
拱墅-和睦 111
拱墅-信义坊 118
拱墅-湖墅 128
滨江-白马湖 138
拱墅-大关 153
拱墅-桥西 160
拱墅-朝晖 169
拱墅-半山 181
拱墅-建国北路 186
拱墅-流水苑 187
拱墅-石桥 187
滨江-奥体 199
滨江-西兴 209
拱墅-申花 238
拱墅-拱宸桥 239
拱墅-三塘 257
滨江-长河 335
富阳-东洲 392
富阳-富春 513
滨江-浦沿 554
滨江-彩虹城 635
滨江-滨江区政府 930
富阳-银湖科技城 986
Name: 区域位置, dtype: int64
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-q84Fc9b7-1684846070290)(output_18_1.svg)]
我们发现在滨江区单价普遍较高,而富阳-银湖科技城比较昂贵
# 看房时间分析
f4 = house['看房时间'].value_counts(ascending=True)
print(f4)
plt.figure(figsize= (9 ,5))#创建画布
plt.xticks(rotation = 90) # 横坐标
plt.plot(f4, linewidth=3, marker='o',
markerfacecolor='blue', markersize=5)
plt.title('看房时间统计')
plt.show()
# 通过图表我们发现,看房的顾客大多都是通过提前预约然后随时观看这个选择来看的。
看房时间 1
具体信息请致电经纪人 68
只周末可看 111
下班后可看 210
有租户需预约 955
提前预约随时可看 6776
Name: 看房时间, dtype: int64
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Igt9VAsB-1684846070292)(output_20_1.svg)]
# 使用饼图查看
print(type(f4))
f4.plot.pie()
<class 'pandas.core.series.Series'>
<Axes: ylabel='看房时间'>
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BR9f4TjV-1684846070293)(output_21_2.svg)]
# 各区域关注度平均值:
house['关注度'] = pd.to_numeric(house['关注度'], errors='coerce',).fillna(0)
f5 = house.groupby('区域位置')['关注度'].mean().to_dict()
print(f5)
x = list(f5.keys())
y = list(f5.values())
plt.figure(figsize= (9 ,5))#创建画布
plt.xticks(rotation = 90) # 横坐标
plt.plot(x, y, linewidth=3, marker='o',markerfacecolor='blue', markersize=5)
plt.title('各区域关注度均值')
plt.show()
{'区域位置': 0.0, '富阳': 0.0, '富阳-东洲': 8.721938775510203, '富阳-富春': 3.9688109161793372, '富阳-富阳': 4.758241758241758, '富阳-江南新城': 7.071428571428571, '富阳-银湖科技城': 13.101419878296147, '富阳-鹿山新城': 2.1052631578947367, '拱墅-万达广场': 13.44, '拱墅-三塘': 19.972762645914397, '拱墅-三墩': 29.71264367816092, '拱墅-三里亭': 15.757575757575758, '拱墅-丝绸城': 17.61764705882353, '拱墅-众安桥': 16.42105263157895, '拱墅-体育场路': 21.821428571428573, '拱墅-信义坊': 18.347457627118644, '拱墅-半山': 19.41988950276243, '拱墅-和平': 21.128205128205128, '拱墅-和睦': 21.135135135135137, '拱墅-大关': 15.627450980392156, '拱墅-天水': 15.625, '拱墅-建国北路': 25.118279569892472, '拱墅-德胜': 30.5, '拱墅-德胜东': 38.541666666666664, '拱墅-拱宸桥': 27.476987447698743, '拱墅-朝晖': 17.644970414201183, '拱墅-桥西': 25.625, '拱墅-武林': 24.348837209302324, '拱墅-流水苑': 23.11764705882353, '拱墅-湖墅': 31.3203125, '拱墅-潮鸣': 24.658823529411766, '拱墅-申花': 25.449579831932773, '拱墅-石桥': 19.56149732620321, '拱墅-笕桥': 11.909090909090908, '拱墅-长庆': 15.883720930232558, '滨江-奥体': 17.417085427135678, '滨江-彩虹城': 21.973228346456693, '滨江-浦沿': 19.862815884476536, '滨江-滨江区政府': 14.706451612903226, '滨江-白马湖': 24.579710144927535, '滨江-西兴': 19.679425837320576, '滨江-长河': 20.755223880597015}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B7aYvq4F-1684846070294)(output_22_1.svg)]
# 户型结构分析
f6 = house['户型结构'].value_counts(ascending=True)
f6.plot.pie()
plt.title('户型结构分析')
# 图标表现出大多为平方出卖。
Text(0.5, 1.0, '户型结构分析')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ftEn5GBN-1684846070295)(output_23_1.svg)]
# 建筑类型:
f7 = house['建筑类型'].value_counts(ascending=True)
f7.plot.pie()
plt.title('建筑类型分析')
# 图标表示大多为板楼建筑
Text(0.5, 1.0, '建筑类型分析')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5C50hf8P-1684846070296)(output_24_1.svg)]
# 房屋朝向:
f8 = house['房屋朝向'].value_counts(ascending=True)
f8.plot.pie()
plt.title('房屋朝向分析')
# 表现为大多面朝南向
Text(0.5, 1.0, '房屋朝向分析')
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cpFumZ2K-1684846070297)(output_25_1.svg)]
# 配备电梯:
f9 = house['配备电梯'].value_counts(ascending=True)
print(f9)
plt.xticks(rotation = 90) # 横坐标
plt.plot(f9, linewidth=3, marker='o',
markerfacecolor='blue', markersize=5)
plt.title('配备电梯统计')
plt.show()
# 表现为大多为配备电梯
配备电梯 1
暂无数据 348
无 1937
有 5476
Name: 配备电梯, dtype: int64
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Azk6abKo-1684846070299)(output_26_1.svg)]
# 房屋用途:
f10 = house['房屋用途'].value_counts(ascending=True)
print(f10)
plt.xticks(rotation = 90) # 横坐标
plt.plot(f10, linewidth=3, marker='o',
markerfacecolor='blue', markersize=5)
plt.title('房屋用途统计')
plt.show()
# 表现为大多为普通住宅
房屋用途 1
车库 2
别墅 357
商住两用 1247
普通住宅 6514
Name: 房屋用途, dtype: int64
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DjrbIZDt-1684846070300)(output_27_1.svg)]
# 卖点核心分析
# 导入词云库
import wordcloud
# 导入jieba库,做分词使用
import jieba
# 精确模式,分词后返回一个列表
ls = jieba.lcut(str(house['核心卖点']))
# 将空格与分词分隔开
txt1 = " ".join(ls)
w = wordcloud.WordCloud(font_path="simkai.ttf", background_color="white",
width=600, height=400, max_font_size=120, max_words=3000)
# 生成词云
w.generate(txt1)
# 词云图片命名
w.to_file("maidian.png")
# 展现出大多为靠近市场、夜市、购物方便、整洁等特点
<wordcloud.wordcloud.WordCloud at 0x283d6a6ad10>
读取写到磁盘的词频图片:“[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-D7yxUwew-1684846070301)(maidian.png)]”
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RoMJx82u-1684846070303)(maidian.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vuNDXzYf-1684846070305)(C:\Users\EVILLIFES\AppData\Roaming\Typora\typora-user-images\image-20230504221358743.png)]