我们知道,由于poi点名称往往对应多个地图上的实际位置,仅仅将poi点名称显示在PowerBI的Bing地图上时,Bing地图不能显示所有的poi点。
要让所有poi点都显示在Bing地图上,需要每个poi点的精准坐标位置。
一、获取poi点的坐标
可以通过高德地图api和百度地图api批量获取点位坐标。高德地图api查询次数限制不够用,所以我用百度地图api来查。
百度地图api查询地址和格式是:http://api.map.baidu.com/place/v2/search?region=昆明&ret_coordtype=gcj02ll&output=json&ak={ak}&query={query}
其中ak需要去百度地图开放平台申请。
百度地图本身可以返回火星坐标,上面的api地址中,【ret_coordtype=gcj02ll】就是返回火星坐标的参数。
我在powerbi中建立了一个函数,这样就可以批量查询poi点位的百度坐标。
let
源 = (word as text) => let
源 = Json.Document(Web.Contents("http://api.map.baidu.com/place/v2/search?region=昆明&output=json&ret_coordtype=gcj02ll&ak={ak}&query="&word)),
results = 源[results],
results1 = results{0},
转换为表 = Record.ToTable(results1),
转置表 = Table.Transpose(转换为表),
提升的标题 = Table.PromoteHeaders(转置表, [PromoteAllScalars=true]),
#"展开的“location”" = Table.ExpandRecordColumn(提升的标题, "location", {"lat", "lng"}, {"lat", "lng"})
in
#"展开的“location”"
in
源
需要把代码中的{ak}环澄自己的ak。
值得注意的是:通过poi点查询的结果并不一定精确,需要人工核对和矫正;有些poi点查不出结果来,所以需要通过地址来查;poi和地址都查不出结果,则需要手动一个一个处理,降低查询精度,获取坐标。
二、将百度地图api查询结果保存为静态文件
为避免每次都要利用百度api去查询坐标,可以一次性将查询结果保存成文件,下次直接加载即可。
三、在PowerBI的Bing地图中批量精确显示poi点位
这个就比较简单了,直接把转换结果导入到PowerBI的Bing地图中,将经纬度分别拖入经纬度字段窗口。
image.png不用把门店地址添加到“位置”窗格。
最后的效果如下: image.png四、反思
主要工作量并不在转换和显示到powerbi中,而在于精确确定每一个poi点位的百度坐标。为什么会这样呢?
一是poi点位数据可能并不精准或规范;
二是百度地图api和百度网页版并不一致,这样一来,在网页地图中查到的poi点位,并不一定能从地图api中获取到数据;
三是百度地图api本身并不准,尤其是查poi点时,如果没有精确匹配的,它会返回一些它认为可能比较接近的结果出来,这些结果往往风马牛不相及。
四是有些点位,无论从百度网页版还是从百度地图api查,都没有结果,这时需要人工矫正。
image.png五是如果要把poi点位显示在别的地图上,则需要先弄清楚该地图支持哪种坐标格式:
火星坐标系:
iOS 地图(其实是高德)
Gogole地图
搜搜、阿里云、高德地图
百度坐标系:
当然只有百度地图
WGS84坐标系:
国际标准,谷歌国外地图、osm地图等国外的地图一般都是这个
具体而言:
如果使用的是百度sdk那么可以获得百度坐标(bd09)或者火星坐标(GCJ02),默认是bd09
如果使用的是ios的原生定位库,那么获得的坐标是WGS84
如果使用的是高德sdk,那么获取的坐标是GCJ02
(详细信息见链接)。如果获取的点位坐标系统与地图不兼容,则需要转换。
如果知道转换方程,可以直接写函数转换。
由于我并不知道转换方程,所以网上找了现成的python代码,代码中提供了转换系数,所以可以根据这些系数写PowerBI函数来转换。
网友评论