基于地圖的數據可視化應用愈來愈廣泛,目前,有很多方法來實現地圖可視化,包括excel的power map包、各種數據分析軟件的地圖庫以及在線交互地圖可視化操作工具,如Echarts、Tableau Public、polyMaps等等。另外還有一種手段就是通過軟件調用百度、google或者其他地圖的api,自己DIY可視化地圖,但是這種辦法需要操作者本身既要對相關軟件的編程熟悉,又要熟悉不同地圖api的具體用法。本文就是用這種手段,以一個簡單的表格文件出發,在不知道相關地點經緯度的情況下,通過python調用百度地圖API實現熱力地圖,這其中需要申請密鑰、批量經緯度換算、轉換成js數據、百度熱力地圖api相關參數的調整等等。
(1)初始數據:csv格式的數據表格
初始數據為2017年1月70個大中城市新建住宅價格指數同比值,直接從國家統計局網站公布的數據copy過來(下圖),數據已整理好,為兩列(城市city、房價指數price),并保存為csv格式。在實際中,我們常常通過爬取網站上萬條地區數據并存為csv格式來分析,在這里為簡化流程,初始數據來源直接copy已有數據。
(2)城市轉換成經緯度第一步:注冊密鑰
在百度地圖api上相關位置的展現是以經緯度為基礎的(這里暫不介紹百度地圖坐標體系與其他地圖的區別),如北京,其經度(longitude)為:116.395645,緯度(latitude)為:39.929986,在這里既需要通過百度的Geocoding API來獲取不同城市的經緯度坐標,又要求將csv數據文件導入python,批量獲取這70個城市的坐標信息。在做這些之前,需要注冊百度地圖api(首先你要用百度的賬號)以獲取免費的密鑰,才能完全使用該api。登錄網址:http://lbsyun.baidu.com/
首頁點擊申請密鑰按鈕,經過填寫個人信息、郵箱注冊等,成功之后在開放平臺上點擊“創建應用”,填寫相關信息,在這里特別說明的是,在IP白名單框里,如果不清楚自己的IP地址,最好設置為:0.0.0.0/0,雖然百度提醒它會有泄露使用的風險,但是有時候你把你自己的IP地址輸進去可能也不行。提交后,在你創建應用的訪問應用(AK)那一欄就是你的密鑰。
(3)城市轉換成經緯度第二步:構造經緯度獲取函數
注冊密鑰后就可以在百度Web服務API下的Geocoding API接口來獲取你所需要地址的經緯度坐標并轉化為json結構的數據,其網址為:
http://lbsyun.baidu.com/index.php?title=webapi/guide/webservice-geocoding
網頁中有相關說明,根據示例URL,采用python3軟件,寫出如下函數:
import json
from urllib.request import urlopen, quote
import requests,csv
import pandas as pd #導入這些庫后邊都要用到
def getlnglat(address):
url = 'http://api.map.baidu.com/geocoder/v2/'
output = 'json'
ak = '你申請的密鑰***'
add = quote(address) #由于本文城市變量為中文,為防止亂碼,先用quote進行編碼
uri = url + '?' + 'address=' + add + '&output=' + output + '&ak=' + ak
req = urlopen(uri)
res = req.read().decode() #將其他編碼的字符串解碼成unicode
temp = json.loads(res) #對json數據進行解析
return temp
(4)城市轉換成經緯度第三步:批量獲取城市經緯度坐標
在構造完獲取坐標函數后,我們就需要用python讀取csv文件的數據,并將city列單獨讀出來,批量獲取經度、緯度坐標,并生成json的數據文件,其代碼如下:
file = open(r'E:\\爬蟲數據分析\調用百度地圖api\point.json','w') #建立json數據文件
with open(r'E:\\爬蟲數據分析\調用百度地圖api\各區域房價.csv', 'r') as csvfile: #打開csv
reader = csv.reader(csvfile)
for line in reader: #讀取csv里的數據
# 忽略第一行
if reader.line_num == 1: #由于第一行為變量名稱,故忽略掉
continue
# line是個list,取得所有需要的值
b = line[0].strip() #將第一列city讀取出來并清除不需要字符
c= line[1].strip()#將第二列price讀取出來并清除不需要字符
lng = getlnglat(b)['result']['location']['lng'] #采用構造的函數來獲取經度
lat = getlnglat(b)['result']['location']['lat'] #獲取緯度
str_temp = '{"lat":' + str(lat) + ',"lng":' + str(lng) + ',"count":' + str(c) +'},'
#print(str_temp) #也可以通過打印出來,把數據copy到百度熱力地圖api的相應位置上
file.write(str_temp) #寫入文檔
file.close() #保存
在這里特別要注意str_temp = '{"lat":' + str(lat) + ',"lng":' + str(lng) + ',"count":' + str(c) +'},',這一行的命令,這是參照百度地圖JavaScript API熱力圖制作的相應格式而生成的,生成的json數據格式為:{"lat":39.92998577808024,"lng":116.39564503787867,"count":124.7},如下圖所示,來自于網址:http://developer.baidu.com/map/jsdemo.htm#c1_15。
(5)生成熱力地圖
接下來就比較簡單,我們先建立一個html文件,將http://developer.baidu.com/map/jsdemo.htm#c1_15
網址中源代碼復制過來,首先將代碼中的ak換成你自己的密鑰;
然后將生成的point.json文件里的數據復制出來,在替換掉var points =[ ]里的內容,即可。這里要注意的是,由于百度地圖JavaScript API熱力圖默認的是以天安門為中心的北京區域地圖,而我們的數據是全國性的,所以這里還需要對熱力圖中“設置中心點坐標和地圖級別”的部分進行修改(見下圖),具體設置可以參考百度創建地圖api中:
http://api.map.baidu.com/lbsapi/creatmap/
自己可以去調試出合適的中心點與地圖級別。
最后,由于我們的大部分price數據(也就是points里的count)都超過了100(默認最大為100),還需要對熱點圖代碼中的點最大值進行設定(這里設為140)。
保存后,用瀏覽器打開,即得到了2017年1月70個大中城市新建住宅價格指數同比的熱力地圖
圖形可以看出,2017年1月房價上漲的熱點地區主要是合肥、南京、杭州一帶,福州、廈門一帶以及廣州一帶。