大数据,机器学习,人工智能可视化Python时空大数据

深圳租房之旅

2020-07-03  本文已影响0人  皮皮大

深圳租房之旅

最近,利用Python爬取了某个网站上关于深圳租房的一些信息,获得了2000*12的数据,然后利用pandas及第三方的库进行了数据清洗、分析和可视化的操作,对深圳的租房现状有了初步分析。

image

声明:数据仅用来学习,未用作任何商业用途

数据爬取

本次的数据是通过爬虫从网上获取的。很久没有爬数据了,把以前写的代码打开看了下,直接拿过来改了很多需要的信息,还是可以直接跑出结果。网站也没有反爬措施,获得数据蛮顺利的

导入各种库

import pandas as pd
import numpy as np
import plotly as py
import plotly_express as px
from plotly.subplots import make_subplots  # 画多个图
import plotly.graph_objects as go
import json
from lxml import etree
import requests
import xlwt
import re
import time

# 显示所有列
# pd.set_option('display.max_columns', None)
# 显示所有行
# pd.set_option('display.max_rows', None)
# 设置value的显示长度为100,默认为50
# pd.set_option('max_colwidth',100)` 

代码

代码中涉及到很多爬虫中需要用到的知识点:

# 本案例仅供学习使用,未用作任何商业用途

class Leyoujia:
  
    # 1. 初始化url和headers
    def __init__(self):
        self.start_url = 'https://shenzhen.leyoujia.com/zf/?n={}'
        self.headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5)  "}   # 需要换成实际的请求头
    
    # 2. 得到全部的URL地址
    def get_url_list(self):
        url_list = [self.start_url.format(i) for i in range(101)]   # 构造URL地址的列表形式并返回
        return url_list
    
    # 3. 发送请求,获取响应
    def parse_url(self, url):
        #print("parsing...", url)
        response = requests.get(url=url, headers=self.headers)
        return response.content.decode('utf-8', 'ignore')  # 返回的是解析内容
     
    # 4. 获取数据
    def get_content_list(self, html_str):
        html = etree.HTML(html_str)
        div_list = html.xpath("/html/body/div[3]/div[2]/div[1]/div[5]/ul/li")

        content_list = []
        for div in div_list:
                item = {"layout":"","location":"","size":"","sizeInside":"",
                        "zhuangxiu":"","numberFloor":"","time":"","name":"","zone":"",
                        "position":"","way":"","money":""}
                
                item["layout"] = div.xpath(".//div[2]/p[2]/span[1]/text()")
                item["location"] = div.xpath(".//div[2]/p[2]/span[2]/text()")
                item["size"] = div.xpath(".//div[2]/p[2]/span[3]/text()")
                item["sizeInside"] = div.xpath(".//div[2]/p[2]/span[4]/text()")
                
                item["zhuangxiu"] = div.xpath(".//div[2]/p[3]/span[1]/text()")
                item["numberFloor"] = div.xpath(".//div[2]/p[3]/span[2]/text()")
                item["time"] = div.xpath(".//div[2]/p[3]/span[3]/text()")
                item["name"] = div.xpath(".//div[2]/p[4]/span[1]/a/text()")
                item["zone"] = div.xpath(".//div[2]/p[4]/span[2]/a[1]/text()")
                item["position"] = div.xpath(".//div[2]/p[4]/span[2]/a[2]/text()")
                item["money"] = div.xpath(".//div[3]/p[1]/span/text()")
                item["way"] = div.xpath(".//div[3]/p[2]/text()")
                
                content_list.append(item)                     
        return content_list
    
    # 5. 保存数据
    def save_content_list(self, content_list):  # content_list是个列表,列表中的元素是item,item是个字典
        with open("leyoujia.txt", "a", encoding="utf-8") as f :
            for content in content_list:
                f.write(json.dumps(content))
                f.write("\n")
                
    # 6. 数据保存到Excel中,使用xlwt(用于写入Excel中)
    def save_to_excel(self, content_list):
        workbook = xlwt.Workbook(encoding='utf-8')
        sheet = workbook.add_sheet('leyoujia') # 设置表名
        head = ["name","layout","location","size","sizeInside","zhuangxiu",
                "numberFloor","time","zone","position","money","way"]  # 设置表头
        for h in range(len(head)):
            sheet.write(0, h, head[h])

        length=len(content_list)
        for j in range(1,length+1):
            sheet.write(j,0,content_list[j-1]["name"])
            sheet.write(j,1,content_list[j-1]["layout"])
            sheet.write(j,2,content_list[j-1]["location"])
            
            sheet.write(j,3,content_list[j-1]["size"])
            sheet.write(j,4,content_list[j-1]["sizeInside"])
            sheet.write(j,5,content_list[j-1]["zhuangxiu"])
            sheet.write(j,6,content_list[j-1]["numberFloor"])
            sheet.write(j,7,content_list[j-1]["time"])
            sheet.write(j,8,content_list[j-1]["zone"])
            sheet.write(j,9,content_list[j-1]["position"])
            sheet.write(j,10,content_list[j-1]["money"])
            sheet.write(j,11,content_list[j-1]["way"])

        workbook.save('./leyoujia.xls')
        
    def main(self):
        # 获得url_list
        url_list = self.get_url_list()
        content_lists = []
        # 在url_list中进行请求的发送,内容的获取以及保存数据
        for url in url_list:
            html_str = self.parse_url(url)
            content_list = self.get_content_list(html_str)
            self.save_content_list(content_list)   # 保存content_list
            content_lists.extend(content_list)  # 将所有的content_list全部追加到content_lists
        self.save_to_excel(content_lists)  # 保存到excel中
                        
if __name__ == '__main__':
    time.sleep(1)
    leyoujia = Leyoujia()
    leyoujia.main()

数据处理

读取数据

将上面保存的数据读取从本地读取出来

image

字段含义

"""
name: 小区的名字
laytou:户型
location:朝向
size:房子建筑面积大小
sizeInside:套内面积大小
zhuangxiu:精装、豪装、普装、毛坯
numberFloor:楼层数
time:建成时间
zone:区
position:所在区的具体位置
money:价格
way:出租方式(整租或者合租)
"""

原始数据信息

image image

删除缺失值

使用的是dropna函数,两个重要的参数:

image

字段处理

为何处理

对于数据中的几个字段,我们需要的只是其中的数字信息,所以需要将它们从整个文本中提取出来。

处理方法

根据表格中文本不同,介绍3种方法:


df1 = df.copy()

# 方式1:通过自定义的函数,传给apply方法
def apply_size(x):
    return float(x.split("面积")[1].split("㎡")[0])

def apply_sizeInside(x):
    return float(x.split("面积")[1].split("㎡")[0])

def apply_way(x):
    return x.split("|")[0]

def apply_room(x):
    return x.split("室")[0]

df1["sizeInside"] = df1["sizeInside"].apply(apply_sizeInside)
df1["size"] = df1["size"].apply(apply_size)
df1["room"] = df1["layout"].apply(apply_room)   # 增加一列数据:卧室个数,从layout中分割出来
df1["way"] = df1["way"].apply(apply_way)

# 方式2:获取文本中的数据,正则表达式
df1["numberFloor"] = df1["numberFloor"].map(lambda str:re.findall(r"\d+",str)[0]).astype(dtype="int")     #

# 方式3:将不需要的内容替换成空格,str.replace
df1["time"] = df1["time"].str.replace("年建成","").astype(dtype="int")

df1.head()

处理前后对比

处理前

image

处理后:增加了room字段

image

同时处理后的字段类型也发生了变化:

image

单个特征可视化

租房方式-way

对租房方式进行可视化:从数据和图形可以直接看出来,绝大多数的人还是选择整租

image image

区域-zone

想对比每个区的房源出租情况,从数据和图形中看出来:

image image

装修方式-zhuangxiu

通过不同的装修方式来分析对比各种房源的数量。不同的参数来实现颜色的变化;

image image image


结论:房源最多的还是集中在精装普装方式上

房子朝向-location

比较房子的朝向来分析对房源数量的影响。前3名分别是:朝南、朝南北、朝北

image

居室个数-room

房子里面卧室的个数对租房的影响,分析不同数量的占比

image

区与房价的关系

在每个区的房租价格肯定是不同的,通过热力图来进行对比

结论:南山和福田的房价整体是偏高的

image image

装修风格与房租价格关系

image

时间与房租价格

随着时间的不断变化,每个区域的房租价格也在跟着变化,通过散点图来观察每个区的价格分布

关内

通过观察关内的数据分布,可以看到:

image-20200703201131031

关外

image

多特征的可视化

在这里以南山区进行分析

作图数据


# 用于制作小提琴图
nanshan = df1[df1["zone"] == "南山"]

# 用于制作柱状图
nanshan_position = nanshan["position"].value_counts().reset_index().rename(columns={"index":"position","position":"number"})

# 用于饼图的制作
nanshan_room = nanshan["room"].value_counts().reset_index().rename(columns={"index":"room","room":"number"})

# 用于散点图的制作
px.scatter(nanshan,x="numberFloor",y="money",color="position",color_continuous_scale='Inferno')

多特征-多图

position_list = nanshan_position.position.tolist()

fig = make_subplots(rows=2, cols=2,  # 1*2的子图
                    subplot_titles=("南山区房源分布","南山区租房价格分布"),
                    specs=[[{"type": "xy"}, {"type": "xy"}],  # 每个子图的类型
                           [{"type": "domain"}, {"type": "xy"}]]
                   )  
# 柱状图
fig.add_trace(go.Bar(x=position_list,  # x=nanshan_position.position.tolist()
                     y=nanshan_position.number.tolist(),
                     text=nanshan_position.number.tolist(),   # 文本显示在外面
                     textposition='outside'
                    ),row=1,col=1)
 
# 小提琴图
for position in position_list:
    fig.add_trace(go.Violin(x=nanshan['position'][nanshan['position'] == position],
                            y=nanshan['money'][nanshan['position'] == position],
                            name=position,box_visible=True,meanline_visible=True),
                            row=1, col=2
                           )
# 饼图    
fig.add_trace(go.Pie(labels=nanshan_room.room.tolist(),
                    values=nanshan_room.number.tolist(),
                    textinfo='label+percent',  # 将labels也显示出来
                    textposition="auto"),    # 信息是否显示,显示在哪里?
             row=2,col=1)

# 折线图
fig.add_trace(go.Scatter(x=nanshan.numberFloor.tolist(),
                         y=nanshan.money.tolist(),
                         mode='markers+text',
                         marker=dict(size=6,
                                     color=nanshan.money.tolist(),
                                     colorscale="haline"),
                        ),
             row=2,col=2)

# fig.update_traces(textposition="outside")
fig.update_layout(title_text="南山区租房情况",  # 两个图的总标题(左上角)
                  height=1000,width=1000,
                  showlegend=False)  # 隐藏右边的图例
fig.show()

image

其他区的数据通过类似的方法得到相应的图形

上一篇 下一篇

猜你喜欢

热点阅读