介绍
在本教程中,您将学习如何使用folium包创建交互式地图。 在此过程中,您将运用新技能来可视化波士顿犯罪数据。
import pandas as pd
import geopandas as gpd
import math
import folium
from folium import Choropleth, Circle, Marker
from folium.plugins import HeatMap, MarkerCluster
你的第一张交互式地图
我们首先使用folium.Map()
创建一个相对简单的地图。
# Create a map
m_1 = folium.Map(location=[42.32,-71.0589], tiles='openstreetmap', zoom_start=10)
# Display the map
m_1
有几个参数可自定义地图的外观:
location
设置地图的初始中心。我们使用波士顿市的纬度(42.32°N)和经度(-71.0589°E)。tiles
会更改地图的样式;在这种情况下,我们选择OpenStreetMap样式。如果您好奇,可以在这里找到其他选项。zoom_start
设置地图的初始缩放级别,较高的值会放大到更接近地图的位置。
现在花点时间通过放大和缩小,或通过向不同方向拖动地图来进行探索。
数据
现在,我们将一些犯罪数据添加到地图中!
我们不会专注于数据加载步骤。相反,您可以想象您正处于pandas DataFrame
crimes 中的一个点。数据的前五行如下所示。
# Load the data
crimes = pd.read_csv("../input/geospatial-learn-course-data/crimes-in-boston/crimes-in-boston/crime.csv", encoding='latin-1')
# Drop rows with missing locations
crimes.dropna(subset=['Lat', 'Long', 'DISTRICT'], inplace=True)
# Focus on major crimes in 2018
crimes = crimes[crimes.OFFENSE_CODE_GROUP.isin([
'Larceny', 'Auto Theft', 'Robbery', 'Larceny From Motor Vehicle', 'Residential Burglary',
'Simple Assault', 'Harassment', 'Ballistics', 'Aggravated Assault', 'Other Burglary',
'Arson', 'Commercial Burglary', 'HOME INVASION', 'Homicide', 'Criminal Harassment',
'Manslaughter'])]
crimes = crimes[crimes.YEAR>=2018]
# Print the first five rows of the table
crimes.head()
Plotting points(绘图点)
为了减少我们需要在地图上显示的数据量,我们(暂时)将注意力集中在白天的抢劫案上。
daytime_robberies = crimes[((crimes.OFFENSE_CODE_GROUP == 'Robbery') & \
(crimes.HOUR.isin(range(9,18))))]
folium.Marker(叶标记)
我们使用folium.Marker()
将标记添加到地图。 下面的每个标记对应于一个不同的抢劫。
# Create a map
m_2 = folium.Map(location=[42.32,-71.0589], tiles='cartodbpositron', zoom_start=13)
# Add points to the map
for idx, row in daytime_robberies.iterrows():
Marker([row['Lat'], row['Long']]).add_to(m_2)
# Display the map
m_2
folium.plugins.MarkerCluster(叶插件标记群集)
如果我们要添加很多标记,则folium.plugins.MarkerCluster()
可以帮助整理地图。 将每个标记添加到MarkerCluster
对象。
# Create the map
m_3 = folium.Map(location=[42.32,-71.0589], tiles='cartodbpositron', zoom_start=13)
# Add points to the map
mc = MarkerCluster()
for idx, row in daytime_robberies.iterrows():
if not math.isnan(row['Long']) and not math.isnan(row['Lat']):
mc.add_child(Marker([row['Lat'], row['Long']]))
m_3.add_child(mc)
# Display the map
m_3
Bubble maps(气泡图)
气泡图使用圆圈而不是标记。 通过改变每个圆圈的大小和颜色,我们还可以显示位置和其他两个变量之间的关系。
我们使用folium.Circle()
创建一个气泡图来迭代添加圆。 在下面的代码单元中,在9-12点发生的抢劫用绿色绘制,而在13-17点发生的抢劫用红色绘制。
# Create a base map
m_4 = folium.Map(location=[42.32,-71.0589], tiles='cartodbpositron', zoom_start=13)
def color_producer(val):
if val <= 12:
return 'forestgreen'
else:
return 'darkred'
# Add a bubble map to the base map
for i in range(0,len(daytime_robberies)):
Circle(
location=[daytime_robberies.iloc[i]['Lat'], daytime_robberies.iloc[i]['Long']],
radius=20,
color=color_producer(daytime_robberies.iloc[i]['HOUR'])).add_to(m_4)
# Display the map
m_4# Create a base map
m_4 = folium.Map(location=[42.32,-71.0589], tiles='cartodbpositron', zoom_start=13)
def color_producer(val):
if val <= 12:
return 'forestgreen'
else:
return 'darkred'
# Add a bubble map to the base map
for i in range(0,len(daytime_robberies)):
Circle(
location=[daytime_robberies.iloc[i]['Lat'], daytime_robberies.iloc[i]['Long']],
radius=20,
color=color_producer(daytime_robberies.iloc[i]['HOUR'])).add_to(m_4)
# Display the map
m_4
请注意folium.Circle()
带有几个参数:
location
是一个列表,其中包含经度和纬度的圆心。radius
设置圆的半径。
请注意,在传统的气泡图中,每个圆的半径都可以变化。我们可以通过定义类似于color_producer()
函数的函数来实现此目的,该函数用于更改每个圆圈的颜色。color
设置每个圆圈的颜色。
color_producer()
函数用于可视化小时对抢劫位置的影响。
Heatmaps(热图)
要创建热图,我们使用folium.plugins.HeatMap()
。 这显示了城市不同区域的犯罪密度,其中红色区域的犯罪事件相对较多。
正如我们对一个大城市的期望一样,大多数犯罪都发生在市中心附近。
# Create a base map
m_5 = folium.Map(location=[42.32,-71.0589], tiles='cartodbpositron', zoom_start=12)
# Add a heatmap to the base map
HeatMap(data=crimes[['Lat', 'Long']], radius=10).add_to(m_5)
# Display the map
m_5
如您在上面的代码单元中看到的,folium.plugins.HeatMap()
带有几个参数:
data
是一个DataFrame,其中包含我们要绘制的位置。radius
(半径)控制热图的平滑度。 较高的值可使热图看起来更平滑(即,间隙较小)。
Choropleth maps(分级统计图)
为了了解不同警区的犯罪情况,我们将创建一个choropleth地图。
第一步,我们创建一个GeoDataFrame,为每个地区分配一个不同的行,并且“ geometry”列包含地理边界。
# GeoDataFrame with geographical boundaries of Boston police districts
districts_full = gpd.read_file('../input/geospatial-learn-course-data/Police_Districts/Police_Districts/Police_Districts.shp')
districts = districts_full[["DISTRICT", "geometry"]].set_index("DISTRICT")
districts.head()
我们还创建了一个名为plot_dict
的熊猫系列,该系列显示了每个地区的犯罪数量。
# Number of crimes in each police district
plot_dict = crimes.DISTRICT.value_counts()
plot_dict.head()
这是非常重要的,plot_dict
与districts
(地区)具有相同的索引-这就是代码知道如何使用适当的颜色匹配地理边界的方式。
使用folium.Choropleth()
类,我们可以创建一个Choropleth图。 如果下面的地图没有为您呈现,请尝试在其他Web浏览器中查看页面。
# Create a base map
m_6 = folium.Map(location=[42.32,-71.0589], tiles='cartodbpositron', zoom_start=12)
# Add a choropleth map to the base map
Choropleth(geo_data=districts.__geo_interface__,
data=plot_dict,
key_on="feature.id",
fill_color='YlGnBu',
legend_name='Major criminal incidents (Jan-Aug 2018)'
).add_to(m_6)
# Display the map
m_6
out12
请注意folium.Choropleth()
带有几个参数:
geo_data
是一个GeoJSON FeatureCollection,其中包含每个地理区域的边界。
在上面的代码中,我们使用__geo_interface__
属性将districts
GeoDataFrame转换为GeoJSON FeatureCollection。data
是一个Pandas Series,其中包含将用于对每个地理区域进行颜色编码的值。key_on
将始终设置为feature.id
。
这是指用于geo_data
的GeoDataFrame和data
中提供的Pandas Series具有相同的索引。 为了理解细节,我们必须更仔细地看一下GeoJSON Feature Collection的结构(其中与“ features”键相对应的值是一个列表,其中每个条目都是一个包含“ id”键的字典)。fill_color
设置颜色比例。legend_name
在地图的右上角标记了图例。
Your turn
设计自己的地图,以确定日本的哪些地区需要额外的地震加固。