% X2 m0 B4 k. r4 y/ \
推荐一个超好用的python包folium, 专门用于地理数据可视化,官方英文教程教程点击这里。
5 Y4 p* R# z, r2 w: Z
6 H$ g& {/ p& j 使用方法很简单,操作如下:
导入包,创建一副世界地图8 F7 h/ `+ E7 J- {
import folium
: |" i( @1 n4 w7 j import pandas as pd
+ a5 u# v% C1 s
5 L, Z0 ?. M3 k2 j9 ~4 @ # define the world map
. b* d. K. u5 o/ `* M e( b world_map = folium.Map()
+ y. s+ x; \ @/ ]+ A- ^& d6 M- D: y, h7 c
# display world map
P; x. e: }) ^/ i' B world_map
1 ? _4 Y. ?' t9 }
6 l4 Y: N. ?; m1 |3 W& ] 2. 输入经纬度,尺度,在这里我们以旧金山(37.7749° N, 122.4194° W)为例。
9 ?( y4 `/ I$ x# |
# San Francisco latitude and longitude values5 ?6 k- O% `* ?7 U8 T9 u
latitude = 37.77; O* C/ `% m# I- A
longitude = -122.42& L2 K1 s6 \: U9 N( i {
8 O: o) p5 u9 z8 k: H9 ] # Create map and display it# p0 U+ l2 O K2 S9 @& | T0 y$ n
san_map = folium.Map(location=[latitude, longitude], zoom_start=12)
5 t& l: R, U4 P9 ^+ w
, ]; }" m) `# B/ J5 K: K% n # Display the map of San Francisco) c) S o" j# P- M
san_map
7 q1 |! A" e4 A9 d) O; q4 | + }- E- S8 {; F% ]3 C$ _
更改地图显示,默认为OpenStreetMap风格,我们还可以选择Stamen Terrain, Stamen Toner等。
9 z' E5 p; P; H2 } # Create map and display it
0 e$ q: g8 C' }0 b/ Z san_map = folium.Map(location=[latitude, longitude], zoom_start=12,tiles=Stamen Toner)
7 H8 ~3 A6 t/ `& ?3 @% G: H/ q
" ~ A- Y! G Z _# W# E1 S- `) W" x2 o 3. 读取数据集(旧金山犯罪数据集)
: @) ^! v; R+ {4 q/ Y$ G# g, l # Read Dataset
7 s9 S1 o) B0 L7 v/ P5 q6 P4 G cdata = pd.read_csv(https://cocl.us/sanfran_crime_dataset)7 u7 M' x7 Z9 u
cdata.head()
* \2 P8 M5 h/ l. f7 Q9 R
, T7 x( z7 W8 O
4. 在地图上显示前200条犯罪数据
& K! l0 l: e/ T: a
# get the first 200 crimes in the cdata
/ F# {6 d% G' s5 ^8 G" V
limit = 200
4 @, {+ ]- S3 ~, o% t3 r( e1 F; t data = cdata.
iloc[0:limit, :]
1 E* F0 W. F9 x) ~' ?( b. Z; H) ]/ e6 k5 _
# Instantiate a feature group for the incidents in the dataframe
( |( @$ G8 ~* f! z, ^6 |# Y( a4 f
incidents = folium.map.FeatureGroup()
6 P9 R2 {% i6 o8 D/ N; e4 a& i
; L7 B8 ~/ v# w # Loop through the 200 crimes and add each to the incidents feature group
# c# _3 G6 _# C1 e9 g) m2 I. {$ @
for lat, lng, in zip(cdata.Y, data.X):
# `+ b+ E" B# [
incidents.add_child(
' ?/ B( K3 n5 j- y% n# y5 R folium.CircleMarker(
+ `) g% w+ Z6 J$ c [lat, lng],
$ A, M$ Z$ z6 z) W! g radius=7, # define how big you want the circle markers to be
( D& y* ^9 U/ E+ x8 [# v0 x0 z color=yellow,
9 b5 w+ u- E j# j7 V
fill=True,
& d$ S( b& z6 g+ m
fill_color=red,
2 }! Z, t- Q. e) N8 Q9 J5 u+ ?9 K5 n
fill_opacity=0.4
0 e; d7 b |: v1 q
)
5 o: X+ I; M+ G6 M5 s4 K* Y
)
0 w- w) O0 ?1 ? W7 _; b! s, G
% X* k% t5 ?: @% l # Add incidents to map
3 Z: O" v* n! k) |/ C) I: f
san_map = folium.Map(location=[latitude, longitude], zoom_start=12)
) }. J& c" u3 v: e$ u& ?
san_
map.add_child(incidents)
, _! U+ V6 v% g
, W7 T6 S. i% C8 h$ X1 Y 5. 添加地理标签
4 n6 u+ _, J' R5 n) e
# add pop-up text to each marker on the map
) f: {* q: T0 T7 n) T1 p, ^ latitudes = list(data.Y)
5 [% }) g; `' a) P! s* o2 O; @ longitudes = list(data.X)
6 b+ Y; ^; L. X2 J0 s6 T
labels = list(data.Category)
, Y% B. V+ F" J$ r" f5 E
% T( S4 Z1 y( J g) y( x for lat, lng, label in zip(latitudes, longitudes, labels):
' }- Q' k0 E8 O* }2 x folium.Marker([lat, lng], popup=label).add_to(
san_map)
: K4 I. Q4 [ S1 m( F
: V8 X; w7 t" z8 z # add incidents to map
9 D/ Q- ~' F8 f: I
san_map.add_child(incidents)
% W7 E& H1 n" d/ W1 U
" p( u6 @2 r- Z$ q 6. 统计区域犯罪总数
4 y2 f, p( H7 M" p+ @) M
from folium import plugins
, p) r. ~* t6 R, {( v( j. }9 c& Y$ ], g! ^' J6 \, N$ s
# lets start again with a clean copy of the map of San Francisco
$ `, `5 n- _* \ san_map = folium.Map(location = [latitude, longitude], zoom_start = 12)
N7 Q1 `7 R5 _& f0 ]# {5 w8 [5 j+ p& ~: P
# instantiate a mark cluster object for the incidents in the dataframe
, h0 L; z) n4 J" b. t9 ~ incidents = plugins.MarkerCluster().add_to(san_map)
" D4 D8 _# m/ D& E0 b9 k) F* @# ~
* l+ p2 t+ q# C2 ?! }7 c3 M# c+ Y2 c5 M( U # loop through the
dataframe and add each data point to the mark cluster
& ?' I$ j; t3 [/ b0 [- f, P
for lat, lng, label, in zip(data.Y, data.X, cdata.Category):
# e( A) q: t- S0 ]: ?
folium.Marker(
+ x" q9 n$ n, L2 b location=[lat, lng],
! m; C# F: H9 t1 P
icon=None,
. E/ `7 J8 M. h$ E, f/ }. c+ t
popup=label,
% j5 v A& ]. [# `: ?* Z ).add_to(incidents)
5 R. L& y4 ?% @+ _% N
/ j( ~, d, J7 T6 l: a1 E% l
# add incidents to map
* M9 ?; E' l" f' Y# I% u
san_map.add_child(incidents)
$ F3 K4 I. F8 M: [. a. z4 y
$ m3 m$ c3 n7 k+ P X
7. 读取geojson文件,可视化旧金山市10个不同Neighborhood的边界
9 L7 x& x, |: a6 y# L( M8 K& d
import json
6 U, z- G( }4 l, l' f$ H import requests
- G5 N# j7 l9 G T) K. L) T
6 A0 G5 Q" G" Z4 ~7 n8 C; X url = https://cocl.us/sanfran_geojson9 C& i m0 q# |
san_geo = f{url}
( V6 g8 ^( [, R8 T; b2 p9 m# F san_map = folium.Map(location=[37.77, -122.4], zoom_start=12)/ I/ q# ]4 z+ H M8 s: e
folium.GeoJson(
1 c6 n7 k% I3 K# W/ W( T/ Z/ |) U san_geo,
' t& I, h: w8 _. P q style_function=lambda feature: {
/ q/ Q3 U( X3 C! _ fillColor: #ffff00,
9 z; x+ v9 Y7 t, G* |* n color: black,: D4 y3 O* U; n. z3 y- _/ X
weight: 2,
1 [( g, P, j+ I, J0 K dashArray: 5, 5* e. U$ f6 E8 r: L% I- N, A
}6 k6 G4 b4 z( U3 {+ s
).add_to(san_map)
& I, k: M- K4 {6 {
0 z* b+ k" e9 M. z- Y1 ~ #display map
3 R. O- b9 e; ~ san_map
H- y1 r- ]- U) n
( S" K) n" i7 e3 r$ z 8. 统计每个区域的犯罪事件数目
: l* F8 k, G: |+ Y
# Count crime numbers in each
neighborhood* N/ _) S- L1 t. ?5 v* q
disdata = pd.DataFrame(cdata[PdDistrict].value_counts())
% I8 Q, u- t4 `* O2 l
disdata.reset_index(inplace=True)
. Z$ Z1 F% ^" C ` disdata.rename(columns={index:Neighborhood,PdDistrict:Count},inplace=True)
6 }' M0 X5 x- w o- }0 t
disdata
7 B! {4 k3 p5 m1 [/ o( k
5 x2 L5 P: _- x7 G) q B u 9. 创建Choropleth Map (颜色深浅代表各区犯罪事件数目)
4 G( X/ Q6 o) i4 i/ }- C- W8 Y
m = folium.Map(location=[37.77, -122.4], zoom_start=12)
: B8 g; [ ? [! Q8 a' [8 w% U- N folium.Choropleth(
! v! A3 K1 r; f: V1 R; w) B
geo_data=san_geo,
. `- k; J2 o* h5 l0 p
data=disdata,
: R& F* C7 |& _5 R4 G" Q j columns=[Neighborhood,Count],
& l* f, J& Q: k$ l' M
key_on=feature.properties.DISTRICT,
8 E# D8 r, V# i #fill_color=red,
8 P& k, `, j+ t6 | z0 P fill_color=YlOrRd,
1 h* _, R( J# n$ ]
fill_opacity=0.7,
; _) v$ Y' N2 b) H4 m
line_opacity=0.2,
+ ]/ H' ?" g+ D) ?" y: y' A8 n9 L
highlight=True,
( u8 r( G9 I& s) u8 A legend_name=Crime Counts in San Francisco
. C& I3 m- t" O2 O0 F4 O ).add_to(m)
$ R, ~8 h4 _# A& M' r8 n# V m
: C, w: ], g/ M) d
- g7 P/ |1 c1 f( m/ d
) i- ^6 M( ?8 J5 V 10. 创建热力图
9 [+ p! x- G2 R, F, D
from folium.plugins import HeatMap) H# w/ {, Q, S# n
& [4 m; x+ o% k
# lets start again with a clean copy of the map of San Francisco% v4 T! h: n, i" l3 }
san_map = folium.Map(location = [latitude, longitude], zoom_start = 12)( h7 `# P7 y/ ~
6 A) U* n H2 I8 M \ i
# Convert data format
/ E& d$ O+ N1 J* I% H& H heatdata = data[[Y,X]].values.tolist()
' Q8 T( x2 _0 k4 P
( F H* d) J3 O8 ? # add incidents to map
; W/ c9 M8 N2 Y% Y3 H3 ? HeatMap(heatdata).add_to(san_map)
9 G% C# K4 V3 U
. M2 B4 w( M4 v6 T san_map
( O8 Z" z1 J3 p. h 5 }4 b; o" J( L
最后,folium还可以用来创建动态热力图,动态路径图等,具体可参考Medium上的这篇文章。
4 o. o7 E4 e' q$ ^! B
实现效果如下图所示 (直接从Medium上抱过来的图,详细代码请点击上述链接)。
7 |6 }3 U1 l) u* y
. Q F: X. {# ~
我的其他回答:
6 g/ \" t4 f6 m. J7 c$ {
' q( u4 f, [- D0 u" N- Z $ A- a2 r' `8 |1 c2 e
$ W' n! S: ]% O9 Y
最近有小伙伴私信我推荐一些学习编程的经验,我给大家几点建议:
! @ |3 s, z6 A3 k' e, f 1. 尽量不去看那些冗长的视频教程,不是说学不到知识,而是,在你学到知识之前,你可能已经睡着了 =_=
# w9 E4 U! W3 K/ f8 U3 e 2. 不要贪多,选一个知名度高的python教程,教学为辅,练习为主。要随时记住,我们学习python的目的在于会用,而不是背过了多少知识点。
0 r( \6 H$ C3 {& u/ ^ 给大家推荐一款我超喜欢的python课程——夜曲编程。我闲没事在上面刷了一些编程题目,竟回想起当年备考雅思时被百词斩支配的恐惧。这款课程对新手小白很适合。虽然有手机app,但我建议你们用网页端学习哈。
8 Z- O$ j0 D. F$ ?1 y 最后,我的终极建议是:无论选什么教程,贪多嚼不烂,好好专注一门课程,勤加练习才是提高编程水平的王道。等基础知识学的差不多了,去Kaggle上参加几场比赛,琢磨琢磨别人的编程思路和方法就完美啦!
& ]/ s6 s- G) g3 M7 }