介紹
在本教程中,您將學習如何使用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
設計自己的地圖,以確定日本的哪些地區需要額外的地震加固。