安装组件
!pip install GDAL-3.1.4-cp37-cp37m-win_amd64.whl
Shapely-1.7.1-cp37-cp37m-win_amd64.whl
Fiona-1.8.18-cp37-cp37m-win_amd64.whl
!pip install folium
软件包引入:
import pandas as pd
import numpy as np
import plotly
import plotly.graph_objects as go #存放图的对象的组件
import chart_studio.plotly as py #在线画图
import plotly.express as px #离线画图
from folium.plugins import Draw
import folium
m = folium.Map()
m
GeoJSON数据格式如下:
{
“type”: “Feature”,
“geometry”: {
“type”: “Point”,
“coordinates”: [125.6, 10.1]
},
“properties”: {
“name”: “Dinagat Islands”
}
}
GeoJSON地图数据生成网站
有三种格式,我们使用OSM。(Mapbox是收费的)
如果不想使用网站的方式,可以使用如下方式一站式服务。和方法一一样。
m = folium.Map()
#添加图层,生成一站式服务。
draw = Draw(export=True, filename="test.geojson")
draw.add_to(m)
m
有一份区域和区域占比的数据要在地图山上绘制出来,beijing和beijing的id相匹配出来。
choropleth(数据;geojson数据;位置,即和哪个做匹配;scope范围,默认是显示全球,这里指定亚洲;color颜色)
fig = px.choropleth(geo,geojson=china,locations='Regions',scope="asia",color='followerPercentage')
fig
使用choropleth功能绘制的地图,就是相当于标定一个在原来的地图上标定一个区域来显示自己要表达的内容,表现形式相对粗糙,没有行政区,道路等相关信息,且板块边界有缺损。只是一个个板块。
Mapbox地图精度更高,需要联网进行绘制。choropleth底图是个白版,行政区域需要自己画。Choroplethmapbox借助了mapbox的底图。
关于添加地图样式的设置:mapbox_style参数可以选择的赋值对象可以参考官网layout.mapbox.style
明确一点指定mapbox_style后,执行程序,系统会自动向后台网址发生请求加载对应的样式,这中间会跟着网络有关系(如果没有挂可能有些地图样式加载不出来)
1.首先如果指定white-bg样式,就直接加载出来了,因为本来绘图的背景就是白色的,也就不用发送网络请求
2.其次有一些自由使用的样式:open-street-map, carto-positron, carto-darkmatter, stamen-terrain, stamen-toner 或者 stamen-watercolor ,比如代码中使用的就是第二个样式
3.最后就是有些必须通过token进行访问:basic, streets, outdoors, light, dark, satellite, 或者 satellite-streets
fig = go.Figure(go.Choroplethmapbox(geojson=china,locations=geo.Regions,z=geo.followerPercentage,
colorscale='blugrn' #可以试错法
))
fig.update_layout(mapbox_style="carto-positron",mapbox_zoom=3,mapbox_center = {
"lat" : 35.9 ,"lon" : 104.2})
fig.update_layout(margin={
"t":0,"b":0,"l":0,"r":0})
fig
如果想在鼠标点击的时候显示中文的北京,则需要在数据geo中改为中文的北京,且geojson的地理数据中id改为中文的北京。
前面都是对于国家行政区域大面积数据的地图可视化,如果要进行某一具体省市或者区域地图可视化,就可以直接使用folium里面的绘图功能。绘图前需要明确一点,既然是具体到某一区域,就要指定具体生成图像后显示的位置,也就是中心点(可以使用地图数据GeoJSON数据生成中的任意方法获取区域中一个点的经纬度),比如要看一下洛杉矶的出租车的运营情况,首先要指定洛杉矶的位置,一般就是经纬度。
lat=37.77
long = -122.42
#zoom_start几层的放大
sanfran_map = folium.Map(location=[lat,long],zoom_start=12)
插曲:
list1=['a','b','c']
list2=[1,2,3]
for i in zip(list1,list2):
print (i)
结果:zip将两个列表进行捆绑为元组
('a', 1)
('b', 2)
('c', 3)
sanfran_map = folium.Map(location=[lat,long],zoom_start=12) #每次都要重新生成一下,要不然之前执行的擦不掉。
incidents = folium.map.FeatureGroup()
for lat, lng, in zip(df_incidents.Y, df_incidents.X):
incidents.add_child(
folium.CircleMarker(
[lat, lng],
radius=5, #直径
color='red',
fill=True, #填充
fill_color='blue', #填充的颜色
fill_opacity=0.6
)
)
sanfran_map.add_child(incidents)
如上就可以把数据显示在地图上。整个过程就是先创建一个地图,指定显示的位置,接着创建一个群组放置标记,标记需要一个个添加,添加的依据就是经纬度数据,顺带着可以设置标记的样式,最终把群组添加到地图画像中完成绘制。
添加标注信息:
添加的标记没有交互的功能,只是显示在地图上,要实现交互的功能就需要添加文本的标注,代码指令:folium.Marker()
sanfran_map2 = folium.Map(location=[lat,long],zoom_start=12)
incidents = folium.map.FeatureGroup()
for lat, lng, in zip(df_incidents.Y, df_incidents.X):
incidents.add_child(
folium.CircleMarker(
[lat, lng],
radius=5,
color='red',
fill=True,
fill_color='blue',
fill_opacity=0.6
)
)
lat1= list(df_incidents.Y)
long1 = list(df_incidents.X)
lables = list(df_incidents.Category)
for lat,long,lable in zip(lat1,long1,lables):
folium.Marker([lat,long],popup=lable).add_to(sanfran_map2)
sanfran_map2.add_child(incidents)
pop的是lable信息。
sanfran_map2 = folium.Map(location=[lat,long],zoom_start=12)
# incidents = folium.map.FeatureGroup()
# for lat, lng, in zip(df_incidents.Y, df_incidents.X):
# incidents.add_child(
# folium.CircleMarker(
# [lat, lng],
# radius=5,
# color='red',
# fill=True,
# fill_color='blue',
# fill_opacity=0.6
# )
# )
lat1= list(df_incidents.Y)
long1 = list(df_incidents.X)
lables = list(df_incidents.Category)
for lat,long,lable in zip(lat1,long1,lables):
folium.Marker([lat,long],popup=lable).add_to(sanfran_map2)
# sanfran_map2.add_child(incidents)
去掉小圆圈,只显示marker。CircleMarker是小圆圈,还可以添加其他多边形。100-200的数据可以用这种形式。
如果要把全部的数据标记都放置在地图上会是什么效果,先不把十几万条数据放置在地图上,先放置3000个数据看看运行情况。结果中标记点密密麻麻,而且鼠标一滑动到这个显示区就会很卡顿,要是对这个地图进行缩小放大需要等待一会。如果是几十万的数据直接放置在上面就会是一个“灾难”,直接让系统崩溃,所以为了解决这个方式,可以将里面的数据点进行聚集,代码指令:MarkerCluster().add_to(),一定的距离产生个球。
from folium.plugins import MarkerCluster
df_incidents = pd.read_csv('geo_pandas.txt')
limit=3000
df_incidents = df_incidents.iloc[0:limit,:]
sanfran_map4 = folium.Map(location=[lat,long],zoom_start=12)
marker_cluster = MarkerCluster().add_to(sanfran_map4)
lat1= list(df_incidents.Y)
long1 = list(df_incidents.X)
lables = list(df_incidents.Category)
for lat,long,lable in zip(lat1,long1,lables):
folium.Marker([lat,long],popup=lable).add_to(marker_cluster)
数据:df_cnt = px.data.gapminder()
回顾一下plotly.express模块绘制散点图的过程,假如要查看一下人均GDP和寿命之间的关系,颜色按照各大洲进行显示。由于数据值较大采用对数方式显示。
px.scatter(df_cnt,x='gdpPercap',y='lifeExp',color='continent',log_x=True,hover_name='country')
animation_frame可以绘制动态散点图,表示的是指定绘制动画依据的字段
px.scatter(df_cnt,x='gdpPercap',y='lifeExp',
color='continent',log_x=True,
hover_name='country',animation_frame='year',
range_x=[100,100000],
range_y=[25,90], )
px.scatter(df_cnt,x='gdpPercap',y='lifeExp',
color='continent',log_x=True,
hover_name='country',animation_frame='year',
range_x=[100,100000],
range_y=[25,90],
size_max=90,
size='pop'
)
可以发现人口多的国家后来人口依然增加,寿命也增加,比如Asia中的中国。
px.bar(df_cnt,x='continent',y='pop',
color='continent',hover_name='country',
animation_frame='year',range_y=[0,4000000000],
)
核心代码:px.density_contour()
fig = px.density_contour(df_cnt, x="gdpPercap", y="lifeExp", color="continent",marginal_y='histogram'
, animation_frame='year', range_y=[25,100])
fig
核心代码:px.density_heatmap()
fig = px.density_heatmap(df_cnt, x="gdpPercap", y="lifeExp", marginal_y="histogram",
animation_frame='year', animation_group='country', range_y=[25,100])
fig.show()
核心代码:px.choropleth()
px.choropleth(gapminder,
locations="iso_alpha",
color="lifeExp",
hover_name="country",
animation_frame="year",
color_continuous_scale='solar',
height=600
)
px.choropleth(df,
locations = 'State_code', # 或者 iso_alpha
color="Murder_per100000",
animation_frame="Year",
color_continuous_scale="oranges",
locationmode='USA-states',
scope="usa",
range_color=(0, 20),
title='Crime by State',
height=600
)
撒花,好累。。。。。