2020,努力做一個無可替代的人!
長文多圖,建議先收藏再看
寫在前面的話
你好,我是小一
又要開始新的系列了,這個系列保證你一定會喜歡
考慮到前面的系列都是基礎內容,而且篇幅還不少
所以這個系列打算多來點實戰專案,像今天這種的,先做他十幾二十個再說。
至於原始碼都會分享出來,一般都會在文末,需要的同學自取
做一下必要的介紹:
- 小一使用的Python版本是3.8
- 開發環境是Pycharm2019.3
- 圖形視覺化使用matplotlib+seaborn+echarts
為了顯示美觀,部分截圖是在Jupyter 下執行的結果,大家不用糾結
使用echarts 是因為小一做過前端的一些開發,對echarts 的使用還相對熟悉點,文章中主要會用echarts 來做熱力圖
ok,開始我們的第一篇實戰
正文
這是一篇關於深圳租房資料分析的文章
文章會對深圳整體、各區域的租房價格、房屋屬性等多個維度進行分析
也會對深圳的租房價格窪地、熱點區域分佈等進行相關探索
首先,今天的資料集來自於之前的爬蟲專案:
今天的分析流程主要分為以下三步:
- 提出問題&問題分析
- 資料預處理
- 視覺化分析與探索
如果對資料分析流程還不是很瞭解的同學可以看看前面的這篇文章:
一、提出問題&問題分析
想必在提出問題之前,避免問題太大太誇張不能完成,我們得先了解一下資料都有什麼
這裡直接拿爬蟲的需求欄位資料看一下
# 資料欄位
city: 城市
house_id:房源編號
house_rental_method:房租出租方式:整租/合租/不限
house_address:房屋地址:城市/行政區/小區/地址
house_longitude:經度
house_latitude:緯度
house_layout:房屋戶型
house_rental_area:房屋出租面積
house_rental_price:房屋出租價格
house_update_time:房源維護時間
house_orientation:房屋朝向
house_tag:房屋標籤
house_floor:房屋樓層
house_elevator:是否有電梯
house_parking:房屋車位
house_water:房屋用水
house_electricity:房屋用電
house_gas:房屋燃氣
house_heating:房屋採暖
create_time:建立時間
house_note:房屋備註
複製程式碼
一共21個欄位,共21750條資料
1.1、資料特徵分析
到這你可能會有疑問了,為什麼先進行這個步驟?
在我們上面的22個特徵中,會存在一些主要特徵
像地址、房租價格、面積這些,是我們重點要分析的特徵,而像房屋用水、用電、採暖這些就屬於次要特徵,可以進行輔助參考
就類似你去租房的時候你會首先考慮房屋的水電嗎?你肯定是看了戶型和價格覺得可以才會繼續問水電,甚至就算水電不符合你的要求你也可能會說服自己租下的
在資料的21個特徵中,其中主要資料特徵包括:
- 出租方式(整租 or 合租)
- 地址(行政區-區域-小區名)
- 經緯度(房源經緯度資料)
- 格局(x室x廳x衛)
- 面積(xx m²)
- 價格(xxxx元/月)
房源編號、建立時間、採暖、備註等特徵為多餘特徵
房源編號是房子的唯一標識,我們用小區名可以替代
深圳是沿海城市,暖氣這個詞似乎很遙遠
建立時間沒有可對比性
如果你的資料時間跨度比較大,可以做環比分析,這個時候時間欄位就有用了,今天我們暫且用不上
剩下的特徵都是次要特徵,主要描述房屋的一些附加屬性,例如車位、樓層、燃氣等
1.2、提出問題
重頭戲來啦,我們需要解決的問題是什麼?
小一我每次搬家找房子的時候都會超級焦慮,每次都是
所以在準備做這個專案時就立刻有一個目標:如何找一個便宜又超值的房子?
嗯!也就是文章的標題,我要租個好房
我們都知道地鐵口周圍的房租會貴很多,那麼我們知道了房源分佈和價格,能不能模擬出城市的地鐵線路?
這,是小一想到的第二個問題
另外,小一目前是做運營商網路資料分析的,所以就想著這個專案能夠對網路的運營優化有一點點幫助,或者有個參考思路也行
這,是小一想到的第三個問題
1.3、問題分析
自己提的問題流著淚也要想出解決方法
對於上面的三個問題,我們首先需要對深圳的租房資料做一個整體統計
通過整體分佈情況再次細分需要研究的資料特徵,通過特徵結果篩選分析確定最終的心儀目標
整體就是一個總—分的思想,從整體中選出符合要求的部分,針對部分再次分析,篩選、分析……
對於本次資料,我們可以從以下幾個問題去進行分析:
- 深圳整體房源出租方式比例是什麼樣的?
- 深圳的房源數量分佈是什麼樣的?
- 房租價格分佈呢?
- 價格相對便宜的房源分佈在哪些區域?
- 這些區域的房租、房源資料分佈?
- ……
這樣我們就可以在目標的導向下,一步步的去細分資料,去靠近目標,並完成最終的探索分析
二、資料預處理
終於到了預處理這一步,前面學習的Pandas、NumPy 都能派上用場了,是不是有點小激動?
問題已經明確,資料也都準備好了,開始我們的第一個難題:資料預處理
資料預處理我們需要處理以下問題:
- 資料統計、分佈情況
- 找出缺失資料,選用合適的方法處理
- 找出異常資料,選用合適的方法處理
- 資料合併重塑
先來看一下資料的分佈情況
一共22個欄位,其中house_note 全部為空,經緯度資料有一條為空,其他全部不為空
等一下,經緯度只有一條空資料,是不是可以先處理一下?
ok,滿足你,看一下缺失經緯度的資料
這裡直接用最簡單粗暴的處理方式:
去百度座標拾取系統輸入房屋地址拿到經緯度資訊
# 使用經緯度填充異常值
df_data.loc[df_data.house_longitude.isnull(), 'house_longitude'] = 114.018609
df_data.loc[df_data.house_latitude.isnull(), 'house_latitude'] = 22.604297
複製程式碼
再來看欄位:22個欄位中,房源編號、房屋備註、房源維護時間、建立時間、供暖等五個欄位可以直接刪除
我們在提出問題的時候已經分析過可以刪除的原因
# 即刪除房源編號、供暖、房屋備註、房源維護時間和建立時間欄位
df_data.drop(columns=['city', 'house_id', 'house_update_time', 'create_time', 'house_heating', 'house_note'],
axis=1, inplace=True
)
複製程式碼
剩餘的欄位中,我們需要挨個處理,一起來看一下
1. 出租方式應該有:整租/合租 這兩種,如果不是的話需要處理【需要處理】
2. 地址中的:可以劃分為行政區+區域+詳細地址【需要處理】
3. 經度&緯度:應該是float 型別,如果不是的話轉換一下即可 【需要處理】
4. 戶型:標準應該是xx室xx廳xx衛,如果不是的話進行合理處理 【需要處理】
5. 出租面積:應該是一個float 型別的數值,如果再嚴格點應該是int 型別 【需要處理】
6. 出租價格:應該是int 型別的數值 【需要處理】
7. 房屋標籤:官方核驗、近地鐵、精裝等標籤都比較有用 【需要處理】
8. 所在樓層:高中低+樓層 【需要處理】
9. 是否有電梯:是|否 【需要處理】
10. 用水、用電:民水民電和商水商電,這兩個欄位可以確定小區的性質 【需要處理】
11. 提供車位:感覺無關緊要,先放著 【暫不處理】
12. 房屋燃氣:感覺無關緊要,先放著 【暫不處理】
複製程式碼
基本上資料的要求都列出來了,目前我們就先按照這個流程來
資料清洗
第一個欄位:出租方式
先統計一下都有哪些房屋出租方式,
看來很規整,整租和合租都整的明明白白,沒有異常資料,不需要再進行處理
第二個欄位:地址
房屋地址的資料格式是行政區-區域-詳細地址
直接通過split 方法進行劃分,劃分為行政區、區域、小區地址三列
等等,如果地址為空呢?剛好是 "--" 的這種形式呢?
對,所以我們先檢測一下是否存在這樣的資料
果然存在,有一條資料。
我們已知它的經緯度,直接通過經緯度去匹配資料集中的周邊小區
可能有人會說:就一條資料,刪了就完事了,還搞這麼麻煩?
如果說這個欄位不是主要欄位,或者我們沒有能力去填充它,那可能刪了就刪了。
題外話:資料清洗的難點在於過程的繁瑣,而不是因為它的技術複雜,希望大家有點點耐心哈
接上面的,利用地址進行欄位切分
# 將地址欄位劃分為行政區、區域和小區地址
df_data['station'] = df_data['house_address'].apply(lambda str: str.split('-')[0])
df_data['area'] = df_data['house_address'].apply(lambda str: str.split('-')[1])
df_data['address'] = df_data['house_address'].apply(lambda str: str.split('-')[2])
複製程式碼
你可能以為這一步就結束了,細心點的同學會發現這樣處理完之後存在空資料
其中有7個區域欄位為空,看看是什麼樣的
中間的區域內容缺失,造成了切分字串的時候為空
這一步小一是這樣處理的
- 通過小區名查詢到區域不為空的同名小區
- 使用同名小區的區域資料進行填充
即用同名小區的區域欄位去填充(後面也會多次用到這個填充方法)
最後只有一條記錄“南山區--聚寧山莊“沒有區域,需要我們手動填充一下。
# 手動填充
df_data.loc[df_data.id == 10909, 'area'] = '西麗'
複製程式碼
第三個欄位:經度&緯度
將資料直接轉換為float 型別即可
第四個欄位:面積
剔除m²,並將資料轉換成int
第五個欄位:戶型
戶型資料應該是規整的xx室xx廳xx衛的格式,這樣我們可以通過正則去匹配一下,如果都匹配到那就正常
import re
# 驗證戶型格式
df_data['house_layout'].map(lambda str: re.findall(r'^\d+室\d廳\d衛', str)[0]).shape[0]
複製程式碼
不幸的是,報錯了,檢查之後發現“未知”的這種戶型
同樣的方法,使用同名小區的戶型眾數進行填充
如果不存在同名小區,則根據房屋的面積進行填充(粗略的標準,見程式碼if 部分)
第六個欄位:房租價格
只保留價格資料,' 元/月'需要刪除,注意空格
這裡使用正則搞定:\d+表示至少為一個0-9的數字
從圖中可以看到,處理後變為單純的數字
第七個欄位:房屋標籤
去掉房屋標籤的頭尾 / ,並通過 / 進行劃分
df_data['house_tag'] = df_data['house_tag'].str.slice(1, -1)
複製程式碼
可以看到,每個記錄中都包括不止一個標籤,到底哪個標籤標記最多?最多是多少次?
我們將在視覺化部分繼續分析
第八個欄位:房屋樓層
這個資料很有迷惑性,先來看一下資料
前面的樓層高中低是根據後面的具體樓層來看的,但是31層樓的高樓層和5層樓的高樓層並不能比較
這裡我們取直接保留前面的樓層範圍,取一個相對值
另外,對於顯示“未知”的樓層,我們通過同名小區的樓層眾數進行填充
處理後效果如下:
第九個欄位:是否有電梯
同樣存在缺失資料,使用和樓層同樣的處理方式進行處理
並且針對無同名小區的資料通過前面的樓層高度資料進行填充
例如:低樓層的預設無電梯
對331 個缺失資料進行了相應的填充
第九、十個欄位:提供停車位&提供燃氣
這兩個欄位屬於我們直接看一下統計情況
缺失資料較多,而且沒有有用的填充方法,這兩個欄位我們瞭解就行
最後兩個欄位:用水&用電
通過水電欄位可以將房屋分為普通住宅、商業住宅、商住兩用三種
(房屋性質這個歡迎補充,這個領域小一真不瞭解,補課也沒查到多少,555)
終於,我們的重頭戲算是落下帷幕了,你會發現,資料清洗的過程就是一個不斷的去尋找方法驗證資料、填充資料的過程。
這個驗證、填充方法一定要合理,要和實際的業務結合,本文中的業務指實際的租房現狀。
讀到這,請思考一個問題,我們的資料現在一定是對的嗎?
三、視覺化分析探索
一起來看看漂亮的圖表吧
同樣,我們在進行視覺化之前,得先明確一下目的:
- 異常資料的檢查與處理
- 單特徵對房租價格的影響
- 多個特徵下房租價格的分佈情況
- 熱力圖探索地鐵路線
對,你沒看錯,通過視覺化進行異常資料的檢查
這是很重要的一步,在預處理的過程中我們並不能直觀的發現異常資料,但是通過視覺化,就一目瞭然了。
先看看一下數值型資料的描述性統計,其中資料值資料包括:房租價格、經緯度、房屋面積
統計包括:均值,中位數,眾數,方差,標準差,最大值,最小值等
其中房屋面積最大1223m²,最小5m²;
房租價格最大25w 元,最小880 元,平均值6398。
這個值,怎麼說呢,要不就是小一見識短,要不就是資料還有異常值。
你怎麼看?
3.1、異常資料檢查與處理
首先先來看房租價格,為什麼先看這個呢?先暫時保密,看看你能不能發現。
對合租和整租資料分開進行視覺化,畫出各自的箱型圖
視覺化的程式碼有點多,需要的同學直接拉文末獲取原始碼
哦豁,是不是有一些值看著有點過分,比如像25w 的那個整租房,1w的那個合租房
到底是什麼神仙房子,租不起的我只想去看看
於是就有了下面這些圖:
第一張是25w/月的整租房,第二張是1w/月的合租(海景房),是你想要的房子嗎?
不過,小一也不是光看豪宅了,還發現了這個圖
像這些,面積比較大的房屋,應該是整租的房屋,而並不是合租房。
所以,一個嚴重的問題出來了:
合租的房屋裡面有整租的房屋,同理,整租的應該也有合租的。
這就是我們遇到的異常資料了,如果只是看分佈很難直觀看出來的。
異常資料找到了,怎麼糾正呢?總不能直接刪掉吧
肯定不能刪,小一我手動查了大概幾十上百個合租房(竟然沒被官方限制),做了如下的探索:
- 首先,通過房屋面積去進行過濾,大於45㎡
- 其次,通過價錢進行過濾,大於4500元
- 接著,通過房屋戶型進行過濾,非一居室的
整合起來就是:面積大於45㎡、房租超過4500元、戶型是兩室及以上,注意是合租房!合租房!合租房!基本都應該是整租房
同樣的操作,小一我又查了幾十上百個整租房(這次還沒被封,哈哈,以後租房一定去你家)
大概確定了價錢低於3800、面積超過55㎡的非一室的整租房基本都是合租房
加上面積是因為一室兩室這種標準太寬泛,而且沒有定數,需要用面積再次限制
處理之後我們再來看一下箱型圖
可以發現:
整租的價格是在3000-25000範圍內,均價為5600,大於50000的房屋佔比較少
合租的價格是在1000-3400範圍內,均值為1900,大於3400的房屋佔比較少
接下來,到了看圖時間,多圖預警
3.2、單特徵的視覺化
先來看出租方式的整體統計
似乎有點單調,那我們把其他的特徵都拎出來看看
我們大概能從27150條記錄中得出這些資料
- 深圳市的整租房源較多,佔比77.34%遠高於合租的22.66%
- 房源的樓層高度分佈很均勻,竟然有0.01% 的地下室出租
- 有電梯的房源佔比較多,為78.98%
- 有3.85%的房屋提供免費車位
- 提供燃氣的房屋佔比90.60%
- 普通住宅的佔比86.45%
繼續看圖:
深圳市房屋出租數量前三的分別是龍崗區、南山區和福田區,分別佔比24.90%、24.22%、18.90%,為房屋出租的主要區域
房屋標籤數量前三的分別是近地鐵、隨時看房、官方核驗
看來某家已經牢牢把握住租房使用者的心思了,連標籤都這麼符合民意
房屋臥室數量:整租型別的出租房臥室數量前三分別是1居室、3居室和2居室;
合租型別的前三分別是4居室、5居室和3居室。其中整租的一居室數量最多
咦,竟然有一個13個臥室的房屋,小一我又好奇了,走,一起去看看
搜了一下這個房子,看房屋介紹應該是公寓,平攤下來一個臥室也有二十多m²,ok,屬於正常資料
看完房屋的基本資訊,心裡大概有了一個底,那接下來我們應該選擇哪個行政區呢?
先來看個行政區整租的價格分佈
選取價格小於15000/月的資料
除了羅湖、福田和南山價格稍高些,其他幾個區的價格分佈都稍低
再來看看各行政區合租的情況
選取價格小於4000/月的資料
從整體來說福田、南山和羅湖的合租房租最低價在1500,而其他區域最低房價在1000附近,
另外,鹽田區和坪山區數量太少,可以不用考慮
小總結:
從房價的分佈來看,龍崗和龍華的房價較低,羅湖、福田和南山的房價較高
房源最多的三個區分別是龍崗、南山和福田。
可以初步確定:便宜的房源->龍崗區最佳、龍華次之;不在乎價格的話優選福田、南山
既然確定了區域,那我們針對這幾個區域再進行分析
3.3、多特徵的視覺化
分析完了單一維度的特徵,接下來需要進行特徵組合分析。
舉個例子:我們前面提出的假設--樓層、車位、燃氣、電梯等會對房租有影響嗎?在分析的時候它們只和房租有關,屬於兩個特徵的相關分析
但是像區域分佈、房屋面積、房租等是可以互相影響的,需要聯立特徵分析,比如福田區的房屋面積和房租的關係、福田區整租的房租分佈等等這些
記住我們的最終目標:確定價值窪地
看一下龍崗區的房源分佈情況
我們把整租的房價選擇小於12000每月,合租的房價選擇小於3800每月
以下區域同此標準
其中,阪田、龍崗中心城區域的房源最多,可以重點考慮。
整租房的價格在3000~5000元左右 ,合租房的價格在1200~1700元之間
龍華區的房源分佈
其中,龍華中心、民治、紅山區域房源最多,可以重點考慮。
整租房的價格在3000~7000元之間, 合租房的價格在1000~2500元之間
再來看關內區域
深圳有一個關內關外的概念,關內指的是市中心的幾個行政區。
福田區的房源分佈
此圖的小提琴圖太過密集,容易引起不適感,換成了箱型圖
福田區整租房屋中,皇崗、石廈和梅林的房源最多,房租價格在4500~8500元之間
福田區合租房屋中,梅林、新洲和景田的房源最多,房租價格在1800~2400元之間
南山區的房源分佈
南山區整租房屋中,前海、蛇口和南山中心房源最多,房租價格在4000~10000元之間
南山區合租房屋中,前海、蛇口和南頭房源最多,房租價格在1600~3000元之間
羅湖區的房源分佈
羅湖區整租房屋中,春風路、地王和黃貝嶺房源最多,房租價格在3000~7000元之間,整體房源較少
羅湖區合租房源相對偏少,房租均價在1800~2200元之間
小總結:
小一直接做了個對比表格,一起看看吧
整租優先區域 |
整租分佈均價 |
合租優先區域 |
合租分佈均價 |
|
---|---|---|---|---|
龍崗區 | 阪田、龍崗中心城 | 3000~5000元 | 阪田、龍崗中心城 | 1200~1700 |
龍華區 | 龍華中心、民治、紅山 | 3000~7000元 | 龍華中心、民治、紅山 | 1000~2500元 |
福田區 | 皇崗、石廈、梅林 | 4500~8500元 | 梅林、新洲、景田 | 1800~2400元 |
南山區 | 前海、蛇口、南山中心 | 4000~10000元 | 前海、蛇口、南頭 | 1600~3000元 |
羅湖區 | 春風路、地王、黃貝嶺 | 3000~7000元 | 無 | 1800~2200元 |
你以為這就完了?當然沒有,上面一大堆推薦區域,到底選哪啊?
想到這的時候,小一的腦海突然冒出兩個詞:單價
對啊,買房有單價,租房也有啊,和買房一樣,我們想要的價值窪地一定是單價低、地段好的區域
3.4、熱力圖探索
基於上面的思考,我們進行了進一步的探索
首先需要對資料進行處理,篩選出上面表中的區域
然後對每個區域計算房屋單價,取單價的倒數作為權重
最後根據百度熱力圖,進行視覺化展示,確定價值窪地
篩選區域資料並計算權重
# 篩選資料
df_data_area = df_data.loc[(df_data.area.isin(area)) &
(df_data.house_rental_method == type) &
(df_data.house_rental_price < max_price),
['house_rental_price', 'house_rental_area', 'house_longitude', 'house_latitude']]
# 計算每平米的房屋價值當做權重
df_data_area['weight'] = 1.0/df_data_area['house_rental_price']/df_data_area['house_rental_area']
複製程式碼
儲存上一步的資料,開啟Echarts 官網選擇熱力圖
在彈出的視窗上載入我們的資料
這一步需要將資料改成熱力圖需要的格式:經度+緯度+權重
同樣我們需要將合租和整租分開作圖,先來看一下熱力圖長什麼樣
這一步需要注意,因為爬取到的房屋經緯度是基於百度座標系,這樣用百度地圖作視覺化底圖是不需要進行經緯度轉換的
emmm,蕃茄炒蛋的顏色,雖然這個顏色不止一次被我和同事們嘲笑,但是官方推薦的就是這個,而且似乎也沒有比這個更好的配色了
上面這個圖是龍崗區整租的推薦區域,放小一點會看的更清楚
再來看龍華區的推薦
福田區的推薦
南山區的推薦
如果你也恰巧準備租房,希望上面的圖會對你有用,不過這個資料是今年1月份的,需要注意噢。
借鑑於這個方法,小一將全市的單價資料做成了熱力圖,希望能夠找到解決第二個設想的方法
因為Echarts的配色去顯示全市的資料會讓人更加不適(主要是餓),這裡用Excel 的三維地圖進行視覺化
放大之後我們看一下具體某個區域的圖
這是福田區和羅湖區的部分截圖,圖中紅色的點表示單價較高的點
如果我們將紅色的點進行連線,是不是就是我們想要的地鐵圖呢?
注意了,靈魂畫家上線了
嗯,好像、似乎、可能、大概有點和地鐵圖對不上
很不情願的承認這個想法失敗了
那有沒有改進方法呢?
小一想了幾個思路,有興趣的同學可以探索一下:
- 利用房屋標籤中的近地鐵欄位
- 設定房租上限,降低較大值的影響
- 深圳的地鐵太密集了,要不換個城市?(手動狗頭)
來看一下這一部分的小總結:
- 通過區域的房源數量和價格分佈確定了優選區域
- 通過探索確定了每個優選區域的價值窪地,並給出了地圖展示
- 探索深圳的地鐵路線圖
總結一下:
本文詳細描述了深圳市租房資料的分析過程,具體從問題思考、問題提出、資料預處理、視覺化探索四個步驟進行展開。
在分析過程中,需要注意幾個細節::
- 圍繞問題有針對性、目的性的展開分析
- 資料清洗過程中,對於主要欄位用正確的方式區填充,而不是刪除
- 資料視覺化可以再次驗證資料的異常值
本次專案中,還存在以下問題待改進:
- 對於整租、合租的異常資料處理需要更詳細的方法
- 資料量較少,需要定期爬取資料進行更新
- 針對區域進行聚類,比如住宅區、商業區,進行網路針對性優化(開頭提出的第三個問題)
同樣的,針對本次專案,我們還可以在後期探索以下問題:
- 對比一線城市深圳,猜想二線城市的資料分佈應該是什麼樣的?
- 如果對房租進行預測,如何選擇特徵,怎麼去建模?
關於原始碼
請在文末原文連結中獲取本節內容的原始碼
寫在後面的話
繼上次5000+字的爬蟲實戰,我以為那是我的上限了,直到又肝了這篇8000+字的分析實戰
其實寫程式碼也就花了半天時間,主要是寫出來就……然後這篇文章就……
不知道你們會不會喜歡這樣子的風格
我已經儘可能的在少貼程式碼了,如果有什麼建議歡迎在留言區留言嗷
真心希望這篇文章能夠對需要租房的朋友有所幫助
碎碎念一下
記得三連支援一下小一,後面我會繼續分享更多的實戰專案。
後面如果沒有按時推文章,那一定是在攢一個大大的乾貨
好了,我們下節見!
原創不易,歡迎點贊噢
文章首發:公眾號【知秋小一】
文章同步:掘金,簡書,csdn
原文連結:《吊打分析師》實戰—我要租個好房