手把手教你用Pandas分析全國城市房價
本文轉載自微信公眾號「數倉寶貝庫」,作者李慶輝。轉載本文請聯系數倉寶貝庫公眾號。
Pandas在配合做網絡數據采集爬蟲時,也能發揮其優勢,可承擔數據調用、數據存儲的工作。將數據存入DataFrame后,可直接進入下一步分析。本例以獲取某房產網站中房價為目標,來體驗一下Pandas的便捷之處。
首先利用requests(需要安裝)庫獲取單個小區的平均價格:
- import requests # 安裝:pip install requests
- # 創建一個Session
- s = requests.Session()
- # 訪問小區頁面
- xq = s.get('https://bj.lianjia.com/xiaoqu/1111027382589/')
- # 查看頁面源碼
- xq.text
- # 找到價格位置附近的源碼為:
- # <span class="xiaoquUnitPrice">95137</span>
- # 切分與解析
- xq.text.split('xiaoquUnitPrice">')[1].split('</span>')[0]
- # '93754'
最終得到這個小區的平均房價。這里使用了將目標信息兩邊的信息進行切片、形成列表再讀取的方法。也可以用第三方庫Beautiful Soup 4來解析。Beautiful Soup是一個可以從HTML或XML文件中提取數據的Python庫,它能夠通過解析源碼來方便地獲取指定信息。
我們構建獲取小區名稱和平均房價的函數:
- # 獲取小區名稱的函數
- def pa_name(x):
- xq = s.get(f'https://bj.lianjia.com/xiaoqu/{x}/')
- name = xq.text.split('detailTitle">')[1].split('</h1>')[0]
- return name
- # 獲取平均房價的函數
- def pa_price(x):
- xq = s.get(f'https://bj.lianjia.com/xiaoqu/{x}/')
- price = xq.text.split('xiaoquUnitPrice">')[1].split('</span>')[0]
- return price
接下來利用Pandas執行爬蟲獲取信息:
- # 小區列表
- xqs = [1111027377595, 1111027382589,
- 1111027378611, 1111027374569,
- 1111027378069, 1111027374228,
- 116964627385853]
- # 構造數據
- df = pd.DataFrame(xqs, columns=['小區'])
- # 爬取小區名
- df['小區名'] = df.小區.apply(lambda x: pa_name(x))
- # 爬取房價
- df['房價'] = df.小區.apply(lambda x: pa_price(x))
- # 查看結果
- df
- '''
- 小區 小區名 房價
- 0 1111027377595 瞰都國際 73361
- 1 1111027382589 棕櫚泉國際公寓 93754
- 2 1111027378611 南十里居 56459
- 3 1111027374569 觀湖國際 88661
- 4 1111027378069 麗水嘉園 76827
- 5 1111027374228 泛海國際碧海園 97061
- 6 116964627385853 東山condo 145965
- '''
可以先用Python的類改造函數,再用鏈式方法調用:
- # 爬蟲類
- class PaChong(object):
- def __init__(self, x):
- self.s = requests.session()
- self.xq = self.s.get(f'https://bj.lianjia.com/xiaoqu/{x}/')
- self.name = self.xq.text.split('detailTitle">')[1].split('</h1>')[0]
- self.price = self.xq.text.split('xiaoquUnitPrice">')[1].split('</span>')[0]
- # 爬取數據
- (
- df
- .assign(小區名=df.小區.apply(lambda x: PaChong(x).name))
- .assign(房價=df.小區.apply(lambda x: PaChong(x).price))
- )
以上網站可能會改版,代碼不適用時需要調整爬蟲代碼。
02全國城市房價分析
中國主要城市的房價可以從https://www.creprice.cn/rank/index.html獲取。該網頁中會顯示上一個月的房價排行情況,先復制前20個城市的數據,然后使用pd.read_clipboard()讀取。我們來分析一下該月的數據(下例中用的是2020年10月數據)。
- import pandas as pd
- import matplotlib.pyplot as plt
- plt.rcParams['figure.figsize'] = (8.0, 5.0) # 固定顯示大小
- plt.rcParams['font.family'] = ['sans-serif'] # 設置中文字體
- plt.rcParams['font.sans-serif'] = ['SimHei'] # 設置中文字體
- plt.rcParams['axes.unicode_minus'] = False # 顯示負號
- dfr = pd.read_clipboard()
- # 取源數據
- dfr.head()
- '''
- 序號 城市名稱 平均單價(元/㎡) 環比 同比
- 0 1 深圳 78,722 +2.61% +20.44%
- 1 2 北京 63,554 -0.82% -1.2%
- 2 3 上海 58,831 +0.4% +9.7%
- 3 4 廈門 48,169 -0.61% +9.52%
- 4 5 廣州 38,351 -1.64% +13.79%
- '''
查看數據類型:
- dfr.dtypes
- '''
- 序號 int64
- 城市名稱 object
- 平均單價(元/㎡) object
- 環比 object
- 同比 object
- dtype: object
- '''
數據都是object類型,需要對數據進行提取和類型轉換:
- df = (
- # 去掉千分位符并轉為整型
- dfr.assign(平均單價=dfr['平均單價(元/㎡)'].str.replace(',','').astype(int))
- .assign(同比=dfr.同比.str[:-1].astype(float)) # 去百分號并轉為浮點型
- .assign(環比=dfr.環比.str[:-1].astype(float)) # 去百分號并轉為浮點型
- .loc[:,['城市名稱','平均單價','同比','環比']] # 重命名列
- )
- df.head()
- '''
- 城市名稱 平均單價 同比 環比
- 0 深圳 78722 20.44 2.61
- 1 北京 63554 -1.20 -0.82
- 2 上海 58831 9.70 0.40
- 3 廈門 48169 9.52 -0.61
- 4 廣州 38351 13.79 -1.64
- '''
接下來就可以對整理好的數據進行分析了。首先看一下各城市的均價差異,數據順序無須再調整,代碼執行效果如圖1所示。
- (
- df.set_index('城市名稱')
- .平均單價
- .plot
- .bar()
- )
圖1 各城市平均房價
各城市平均房價同比與環比情況如圖2所示。
- (
- df.set_index('城市名稱')
- .loc[:, '同比':'環比']
- .plot
- .bar()
- )
圖2 各城市平均房價同比和環比
將同比與環比的極值用樣式標注,可見東莞異常突出,房價同比、環比均大幅上升,如圖3所示。
- (
- df.style
- .highlight_max(color='red', subset=['同比', '環比'])
- .highlight_min(subset=['同比', '環比'])
- .format({'平均單價':"{:,.0f}"})
- .format({'同比':"{:2}%", '環比':"{:2}%"})
- )
圖3 各城市平均房價變化樣式圖
繪制各城市平均單價條形圖,如圖4所示。
- # 條形圖
- (
- df.style
- .bar(subset=['平均單價'], color='yellow')
- )
圖4 各城市平均單價樣式圖
將數據樣式進行綜合可視化:將平均單價背景色設為漸變,并指定色系BuGn;同比、環比條形圖使用不同色系,且以0為中點,體現正負;為比值加百分號。最終效果如圖5所示。
- (
- df.style
- .background_gradient(subset=['平均單價'], cmap='BuGn')
- .format({'同比':"{:2}%", '環比':"{:2}%"})
- .bar(subset=['同比'],
- color=['#ffe4e4','#bbf9ce'], # 上漲、下降的顏色
- vmin=0, vmax=15, # 范圍定為以0為基準的上下15
- align='zero'
- )
- .bar(subset=['環比'],
- color=['red','green'], # 上漲、下降的顏色
- vmin=0, vmax=11, # 范圍定為以0為基準的上下11
- align='zero'
- )
- )
圖5 各城市平均房價綜合樣式圖
本文摘編于《深入淺出Pandas:利用Python進行數據處理與分析》,經出版方授權發布。
作者:李慶輝,數據產品專家,某電商公司數據產品團隊負責人,擅長通過數據治理、數據分析、數據化運營提升公司的數據應用水平。