Python数据清洗与可视化——北京租房数据统计分析05
北京租房數據統計分析
5.1數據的爬取
代碼:
# 5北京租房數據統計分析 # 5.1數據的爬取 import pandas as pd import numpy as np file_path=open(r"D:\python課設\數據\數據\5、北京租房數據統計分析\鏈家北京租房數據.csv") file_data=pd.read_csv(file_path,encoding="utf-8") file_data運行結果:
首先使用pandas的read_csv()方法進行數據的讀取,然后就能夠看到相應的表格信息。
5.2區域的房源總量的熱力圖分析
5.2.1數據去重:
代碼:
# 先做數據預處理 file_data.duplicated()運行結果:
先做數據預處理,將重復的數據做去重處理,我們可以看到使用duplicated()可以返回一組布爾數組,重復的部分返回值為FALSE,不重復的為True。
代碼:
filed_data=file_data.drop_duplicates() filed_data運行結果:
使用drop_duplicates()方法對數據做去重處理,去除重復的數據,方便后面繪圖計算以及其他操作。
5.2.2去除重復值
代碼:
# 刪除缺失的數據 data=filed_data.dropna() data運行結果:
使用dropna()的方法刪除空值,做數據進一步的處理,方便后面繪圖計算以及其他操作。
5.2.3數據類型的轉化
代碼:
# 剛我搞完了AK碼的申請,現在我開始進行后面的數據處理,由于我們在這里,存在著熱圖查看需要準確經緯度 # 位置所以需要在這里把詳細的部分做數據拼接 data["位置"]="北京市"+data["區域"].values+"區"+data["小區名稱"].values data運行結果:
在這里顯示熱力圖需要調用百度地圖的API,就需要我們申請一個AK碼,方便調用,然后還需要我們提供特別需要顯示的經緯度。
這個地方比較復雜,所以我將會在另一篇博客中詳細的論述這個部分的內容。
5.2.4導出熱力圖經緯度
代碼:
# _*_ coding:utf-8 _*_ import requests import pandas as pd import time import jsonclass LngLat:# def __init__(self):# self.headers = {# "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.100 Safari/537.36"}# self.proxies = {# "http": "http://61.135.217.7:80",# "http": "http://118.190.95.43:9001",# "http": "http://180.122.147.67:37153",# "http": "http://118.190.95.35:9001",# "http": "http://119.5.0.11:808",# "http": "http://106.56.102.192:8070"# }# 讀取數據def read_data(self):file_path=open(r"D:\python課設\數據\數據\5、北京租房數據統計分析\鏈家北京租房數據.csv")file_data = pd.read_csv(file_path)duplicate_removal = file_data.drop_duplicates()house_names = duplicate_removal['位置']house_names = house_names.tolist()return house_namesdef get_url(self):url_temp = "http://api.map.baidu.com/geocoder/v2/?address={}&output=json&ak=NnQokv12fkyf4YoG59j9fRbGq4G8Lb4K&callback=showLocation"# ak = 'NnQokv12fkyf4YoG59j9fRbGq4G8Lb4K'house_names = self.read_data()return [url_temp.format(i) for i in house_names]# 發送請求def parse_url(self, url):while 1:try:r = requests.get(url)except requests.exceptions.ConnectionError:time.sleep(2)continuereturn r.content.decode('utf-8')def run(self):li = []urls = self.get_url()for url in urls:data = self.parse_url(url)str = data.split("{")[-1].split("}")[0]try:lng = float(str.split(",")[0].split(":")[1])lat = float(str.split(",")[1].split(":")[1])except ValueError:continue# 構建字典dict_data = dict(lng=lng, lat=lat, count=1)li.append(dict_data)f = open(r"D:\python課設\經緯度信息.txt",'w', 'w')f.write(json.dumps(li))f.close()print('寫入成功')if __name__ == '__main__':execute = LngLat()execute.run()運行結果:
首先讀取鏈家北京租房數據.csv的數據,位置信息獲取,然后使用request獲取相關的經緯度信息,然后將處理好的經緯度數據寫入到txt文件中方便后面進行熱力圖的繪制。
5.2.5 熱力圖繪制
代碼:
<!DOCTYPE html> <html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="viewport" content="initial-scale=1.0, user-scalable=no" /><script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=eYTWvbz8Z1lszcRQWrkbOB6RQQOEsDlC"></script><script type="text/javascript" src="http://api.map.baidu.com/library/Heatmap/2.0/src/Heatmap_min.js"></script><script src="https://code.jquery.com/jquery-3.3.1.min.js"></script><title>熱力圖功能示例</title><style type="text/css">ul,li {list-style: none;margin: 0;padding: 0;float: left;}html {height: 100%}body {height: 100%;margin: 0px;padding: 0px;font-family: "微軟雅黑";}#container {height: 800px;width: 100%;}#r-result {width: 100%;}</style> </head><body><div id="container"></div><div id="r-result">上傳文件 : <input type="file" name="file" multiple id="fileId" /><button type="submit" name="btn" value="提交" id="btn1" onclick="check()">提交</button><input type="button" onclick="openHeatmap();" value="顯示熱力圖" /><input type="button" onclick="closeHeatmap();"value="關閉熱力圖" /></div> </body></html> <script type="text/javascript">var points = [];function check() {var objFile = document.getElementById("fileId");if (objFile.value == "") {alert("不能空")}var files = $('#fileId').prop('files'); //獲取到文件列表console.log(files.length);if (files.length == 0) {alert('請選擇文件');} else {for (var i = 0; f = files[i]; i++) {var reader = new FileReader(); //新建一個FileReaderreader.readAsText(files[i], "UTF-8"); //讀取文件reader.onload = function (evt) { //讀取完文件之后會回來這里points = jQuery.parseJSON(evt.target.result);}}} }var map = new BMap.Map("container"); // 創建地圖實例var point = new BMap.Point(116.418261, 39.921984);map.centerAndZoom(point, 12); // 初始化地圖,設置中心點坐標和地圖級別map.enableScrollWheelZoom(); // 允許滾輪縮放if (!isSupportCanvas()) {alert('熱力圖目前只支持有canvas支持的瀏覽器,您所使用的瀏覽器不能使用熱力圖功能~')}//詳細的參數,可以查看heatmap.js的文檔 https://github.com/pa7/heatmap.js/blob/master/README.md//參數說明如下:/* visible 熱力圖是否顯示,默認為true* opacity 熱力的透明度,1-100* radius 勢力圖的每個點的半徑大小 * gradient {JSON} 熱力圖的漸變區間 . gradient如下所示* {.2:'rgb(0, 255, 255)',.5:'rgb(0, 110, 255)',.8:'rgb(100, 0, 255)'}其中 key 表示插值的位置, 0~1. value 為顏色值. */heatmapOverlay = new BMapLib.HeatmapOverlay({ "radius": 20 });map.addOverlay(heatmapOverlay);heatmapOverlay.setDataSet({ data: points, max: 15 });//是否顯示熱力圖function openHeatmap() {heatmapOverlay.setDataSet({ data: points, max: 15 });heatmapOverlay.show();}function closeHeatmap() {heatmapOverlay.hide();}closeHeatmap();function setGradient() {/*格式如下所示:{0:'rgb(102, 255, 0)',.5:'rgb(255, 170, 0)',1:'rgb(255, 0, 0)'}*/var gradient = {};var colors = document.querySelectorAll("input[type='color']");colors = [].slice.call(colors, 0);colors.forEach(function (ele) {gradient[ele.getAttribute("data-key")] = ele.value;});heatmapOverlay.setOptions({ "gradient": gradient });}//判斷瀏覽區是否支持canvasfunction isSupportCanvas() {var elem = document.createElement('canvas');return !!(elem.getContext && elem.getContext('2d'));} </script>運行結果:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-FXPz7EQG-1640703659534)(https://gitee.com/wu-xiaofang/image/raw/master/202112282115879.png)]
5.3 戶型數量和歡迎度的條形圖分析
5.3.1做戶型數量分析
代碼:
# 5.3 戶型數量和歡迎度的條形圖分析 # 先進行戶型的數量分析 import numpy as np def all_house(arr):arr=np.array(arr)key=np.unique(arr)result={}for k in key:mask=(arr==k)arr_new=arr[mask]v=arr_new.sizeresult[k]=vreturn result # 獲取用戶戶型數據 house_array=file_data["戶型"] house_info=all_house(house_array) house_info運行結果:
進行戶型的數量分析,使用 key=np.unique(arr),獲取不同的戶型數據集,然后定義函數對戶型進行分組,定義一個字典儲存分類好的數據,鍵是戶型,值是戶型的數量,最后調用函數,對戶型進行數據的處理。
5.3.2使用字典推導處理dataframe
代碼:
# 使用字典推導 house_type=dict((key,value)for key,value in house_info.items()if value>50) show_house=pd.DataFrame({"戶型":[x for x in house_type.keys()],"數量":[x for x in house_type.values()]}) show_house運行結果:
對戶型數量>50的數據進行字典推導式,使用字典推導式來快速的生成一個字典,生成一個戶型以及數量對應的字典,然后將這些數據再解析生成一個DataFrame對象,方便后面做數據的可視化。
5.3.3條形圖繪制戶型數據
代碼:
# 使用條形圖將戶型數據做展示import matplotlib.pyplot as plt import matplotlibmatplotlib.rcParams['font.sans-serif'] = ['SimHei'] matplotlib.rcParams['axes.unicode_minus'] = Falsehouse_type=show_house["戶型"] house_type_nums=show_house["數量"] house_type_nums """ 繪制水平條形圖方法barh 參數一:y軸 參數二:x軸 """ plt.barh(range(13), house_type_nums, height=0.7, color='steelblue', alpha=0.8) # 從下往上畫 plt.yticks(range(13), house_type) plt.xlim(0,2700) plt.xlabel("數量") plt.title("戶型數據") for x, y in enumerate(house_type_nums):plt.text(y + 0.2, x - 0.1, '%s' % y) plt.show()運行結果:
繪制條形圖:
pyplot并不默認支持中文顯示,需要rcParams修改字體來實現
記得添加上
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] matplotlib.rcParams['axes.unicode_minus'] = False防止亂碼,同時還需要添加上這兩個關于文字顯示,第一個是用來正常顯示中文標簽,第二個是用來正常顯示正負標簽。
5.4各區域的房源數量和租金情況的柱狀圖和折線圖分析
5.4.1計算平均租金
創建新列
代碼:
# 平均租金分析 # 計算平均租金 df_all=pd.DataFrame({"區域":data["區域"].unique(),'房租總金額':[0]*13,"總面積(m平方)":[0]*13}) df_all運行結果:
添加列值
代碼:
sum_price=data["價格(元/月)"].groupby(file_data["區域"]).sum() sum_area=data["面積(㎡)"].groupby(file_data["區域"]).sum() # 將值添加進來 df_all["房租總金額"]=sum_price.values df_all["總面積(m平方)"]=sum_area.values df_all運行結果:
計算每平米租金
代碼:
# 定義函數計算每平米的租金 df_all["每平米租金"]=round(df_all["房租總金額"]/df_all["總面積(m平方)"],2) # 計算并且保留兩位小數 df_allSS運行結果:
合并房源數據
代碼:
# 合并房源數據以及我們的租金數據 df_merge=pd.merge(df_all,homes) df_merge運行結果:
先添加兩列為后面加數據列做準備計算房租總金額以及總面積最后定義函數計算每平米的租金,合并房源數據以及我們的租金數據,就可以得到各區域完整的房源數據。
5.4.2 各區域的房源數量和租金情況的柱狀圖和折線圖分析
代碼:
# 5.4各區域的房源數量和租金情況的柱狀圖和折線圖分析import matplotlib.ticker as mtick from matplotlib.font_manager import FontProperties num=df_merge['數量'] price=df_merge['每平米租金'] l=[i for i in range(13)] plt.rcParams['font.sans-serif']=['SimHei'] lx=df_merge['區域'] fig=plt.figure() ax1=fig.add_subplot(111) ax1.plot(l,price,'or-',label='價格') for i,(_x,_y) in enumerate(zip(l,price)):plt.text(_x,_y,price[i],color='black',fontsize=10,rotation=30) ax1.set_ylim([0,200]) ax1.set_ylabel('價格') plt.legend(prop={'family':'SimHei','size':8},loc='upper left') ax2=ax1.twinx() plt.bar(l,num,alpha=0.3,color='green',label='數量') ax2.set_ylabel('數量') ax2.set_ylim([0,2000]) plt.legend(prop={'family':'SimHei','size':8},loc='upper right') plt.xticks(l,lx) plt.xticks(rotation=0.3) plt.show()運行結果:
在這里將enumerate,zip函數的結合使用:
在這里可以看到i與_x均是索引值,用來表示表示坐標值上的值,y則是每平米的租金
-
enumerate函數:遍歷一個序列的同時追蹤當前元素的索引。
-
zip 將列表,元祖或其他序列的元素配對,新建一個元祖構成的列表
2.plt.text()函數用于設置文字說明。
-
x,y:表示坐標值上的值
-
string:表示說明文字
-
fontsize:表示字體大小
-
verticalalignment:垂直對齊方式 ,參數:[ ‘center’ | ‘top’ | ‘bottom’ | ‘baseline’ ]
-
horizontalalignment:水平對齊方式 ,參數:[ ‘center’ | ‘right’ | ‘left’ ]
5.5面積區間的市場占有率的餅狀圖分析
5.5.1面積區間分析
代碼:
# 5.5面積區間的市場占有率的餅狀圖分析 # 面積區間分析 print("房屋最大面積為%d㎡"%(data["面積(㎡)"].max())) print("房屋最小面積為%d㎡"%(data["面積(㎡)"].min())) # 最高值,最小值 print("房屋最高值為%d(元/月)"%(data["價格(元/月)"].max())) print("房屋最小值為%d(元/月)"%(data["價格(元/月)"].min()))運行結果:
使用min(),max()函數求最大最小值。
5.5.2數據預處理
代碼:
area_divide=[1,30,50,70,90,120,140,160,1200] area_cut=pd.cut(list(data["面積(㎡)"]),area_divide) area_cut_data=area_cut.describe() area_cut_data # =area_cut_data.dropna()運行結果:
使用pandas.cut進行數據的分箱操作,將這里完整的租房數據分割成為離散的區間。按照這個集合[1,30,50,70,90,120,140,160,1200]進行數據的劃分。
5.5.3繪制餅狀圖
代碼:
import numpy as np area_percentage=(area_cut_data["freqs"].values)*100 np.set_printoptions(precision=2) lables=['30平方米以下','30-50平方米以下','50-70平方米','70-90平方米','90-120平方米','120-140平方米','140-160平方米','160平方米'] plt.axes(aspect=1) plt.pie(x=area_percentage,labels=lables,autopct='%.2f%%',shadow=True,labeldistance=1.2,startangle=90,pctdistance=0.7) # 圖例放在圖標位置 plt.legend(bbox_to_anchor=(1.05, 1), loc=3, borderaxespad=0.) plt.show()運行結果:
numpy.set_printoptions()
參數:
numpy.set_printoptions(precision=None, threshold=None, edgeitems=None, linewidth=None, suppress=None, nanstr=None, infstr=None, formatter=None)[source]參數:
precision:int,可選,浮點數輸出的精度位數(默認為8)。
閾值:int,可選,觸發匯總而不是完全repr的數組元素的總數(默認為1000)。
edgeitems:int,可選,在每個維度的開始和結束處的摘要中的數組項數(默認值為3)。
linewidth:int,可選,用于插入換行符的每行字符數(默認為75)。
suppress:bool,可選,是否使用科學計數法抑制小浮點值的打印(默認值為False)。
nanstr:str,可選,浮點數的字符串表示不是數字(默認為nan)。
infstr:str,可選,浮點無窮大的字符串表示形式(默認inf)。
格式化程序:可調用的dict,可選,如果不是無,鍵應該指示相應格式化功能應用的類型。Callables應該返回一個字符串。未指定的類型(通過其相應的鍵)由默認格式化程序處理。可以設置格式化程序的單個類型有:
- ‘bool’
- ‘int’
- ‘timedelta’ : a numpy.timedelta64
- ‘datetime’ : a numpy.datetime64
- ‘float’
- ‘longfloat’ : 128-bit floats
- ‘complexfloat’
- ‘longcomplexfloat’ : composed of two 128-bit floats
- ‘numpy_str’ : types numpy.string_ and numpy.unicode_
- ‘str’ : all other strings
可用于一次設置一組類型的其他鍵有:
-
‘all’ : sets all types
-
‘int_kind’ : sets ‘int’
-
‘float_kind’ : sets ‘float’ and ‘longfloat’
-
‘complex_kind’ : sets ‘complexfloat’ and ‘longcomplexfloat’
-
‘str_kind’ : sets ‘str’ and ‘numpystr’
pyplot.pie
繪制餅圖
matplotlib.pyplot.pie(x, explode=None, labels=None, colors=None, autopct=None,pctdistance=0.6, shadow=False, labeldistance=1.1,startangle=None, radius=None, counterclock=True,wedgeprops=None, textprops=None, center=(0, 0), frame=False,rotatelabels=False, *, data=None)參數解析:
加的這一句是為了防止圖例和圖標重合,
plt.legend(bbox_to_anchor=(1.05, 1), loc=3, borderaxespad=0.)=False, *, data=None)
餅圖繪制就完成了。
總結
以上是生活随笔為你收集整理的Python数据清洗与可视化——北京租房数据统计分析05的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 瓜子云的任务调度系统
- 下一篇: 一条sql语句在mysql中如何执行的