% J& r5 T& ~% B% f F! ?- G; v
推荐一个超好用的python包folium, 专门用于地理数据可视化,官方英文教程教程点击这里。
7 }+ v) K q3 Z& E$ e0 C& D
- q+ H5 r# e1 H4 U% s. Q4 c5 J
使用方法很简单,操作如下:
导入包,创建一副世界地图+ D% ~ R/ |: l6 v. E! A/ T* E
import folium
5 `6 A* o. W6 f2 J+ K4 ~ import pandas as pd
' l5 J+ \# }6 ` ^0 T
2 J$ R* O5 [; \% G3 p/ W7 r # define the world map, ?! a/ |* Q ~
world_map = folium.Map()
$ g) [6 |# u9 y' V
# H0 {7 K2 \2 @* U # display world map
+ X6 a3 b; J* G+ F9 z world_map
4 S2 F U7 f) }# m % m7 I2 z& y* J; [7 ?
2. 输入经纬度,尺度,在这里我们以旧金山(37.7749° N, 122.4194° W)为例。
) ~3 u9 E4 g4 H* y
# San Francisco latitude and longitude values
7 u# T$ Z7 N! s( N latitude = 37.77( ?* C+ H! e. Y
longitude = -122.42
7 E+ ?7 i0 R$ s- X- F1 s0 f
; f8 [& L7 C n) }/ D6 Y5 E # Create map and display it
0 I+ K9 E5 |4 { san_map = folium.Map(location=[latitude, longitude], zoom_start=12)
5 V& Y* I! a' v% x/ @
8 j# D. |/ V( j- N( t # Display the map of San Francisco
( Q2 \5 C a' y [$ M l/ K san_map
! X" M+ C) S+ z: i
6 p0 h( y! f. G/ x 更改地图显示,默认为OpenStreetMap风格,我们还可以选择Stamen Terrain, Stamen Toner等。
( x1 Q; b3 n9 `* m* v* _+ t # Create map and display it8 r$ Q3 v( S. |3 `( C4 n3 K
san_map = folium.Map(location=[latitude, longitude], zoom_start=12,tiles=Stamen Toner)
" d9 e8 N2 J" @) P0 [$ J2 D7 n- k
0 M2 T* e% k3 L* Y' M: Z0 H 3. 读取数据集(旧金山犯罪数据集)
& X2 G+ a0 H2 r! w9 P8 b/ `
# Read Dataset
$ v% ~9 K, `5 P6 h, f cdata = pd.read_csv(https://cocl.us/sanfran_crime_dataset)
: c6 t# K( `1 k cdata.head()
% B& L1 ]9 R8 l: ~4 E k( q
$ b* F: x4 m+ @ 4. 在地图上显示前200条犯罪数据
* a" s" m! Q# m7 ^( B; h/ l1 ]) Z" D # get the first 200 crimes in the cdata
h; R7 E8 L* S: a% f8 v) ^$ Q
limit = 200
) f' i+ j( S' a/ g# r3 E
data = cdata.
iloc[0:limit, :]
! K) V( ~6 e( }$ `
9 S$ B3 y$ m( _6 ]9 n # Instantiate a feature group for the incidents in the dataframe
% S) v# \/ O1 W* t incidents = folium.map.FeatureGroup()
) r! A" ] F8 T* _9 T
{( v& r* l# O( E2 p # Loop through the 200 crimes and add each to the incidents feature group
% L' n; |1 E f; y1 {% u$ N for lat, lng, in zip(cdata.Y, data.X):
/ {8 I- _# T9 C: ?, O3 \ incidents.add_child(
) j+ S) b9 t6 ]: T" D
folium.CircleMarker(
) W, ]2 u {! C: H' Z [lat, lng],
! \" }+ X: a* V" |
radius=7, # define how big you want the circle markers to be
" q! k0 |1 q2 s' ]% z8 J color=yellow,
" Z& W j7 x! d2 R, _4 ?. K, O
fill=True,
4 f9 z' I) c6 C9 T2 j; B# \5 v fill_color=red,
; R: ?5 C) U" ?* A
fill_opacity=0.4
1 |6 L1 p; s+ m2 \ \' O
)
8 ~4 f) o- f8 {* t. x9 n/ b
)
4 i3 G. y# [! M9 \: \" \
7 D9 D4 Q! K, ^+ ^ # Add incidents to map
2 M& g. c) a7 q1 X san_map = folium.Map(location=[latitude, longitude], zoom_start=12)
: B D1 p- R- L1 m" l6 _6 O
san_
map.add_child(incidents)
' O% U" W. M4 N: ~% ~
% e2 w- x3 K' t' l6 }0 z
5. 添加地理标签
5 F+ w U& J: g3 @2 d
# add pop-up text to each marker on the map
( r$ c! k3 x4 o( Q) E latitudes = list(data.Y)
: w( b2 Q. O- r! w. g+ Z+ J! Y- B- L
longitudes = list(data.X)
k/ u9 Z( U) ~ labels = list(data.Category)
" B* t: E4 G! q& w! i" T
: F( P( h) d$ p9 {0 V8 j for lat, lng, label in zip(latitudes, longitudes, labels):
/ c9 g7 f9 q; B, s# w0 Y
folium.Marker([lat, lng], popup=label).add_to(
san_map)
% \( w& l) i5 m o6 y. v( z- r
, ^9 c2 ], b! f # add incidents to map
1 O$ y# I0 n- C8 Z0 `& ]$ G5 r! a) r
san_map.add_child(incidents)
/ K7 s9 t) X- G: z, K: s
% R: X. g0 X, Z! | 6. 统计区域犯罪总数
( Q% u" N2 a5 O2 o from folium import plugins
7 Z4 M7 [3 Z& Z0 X
% d: j; @9 X. c# G& A; P1 J # lets start again with a clean copy of the map of San Francisco
8 _7 j; d* i1 ?+ r' x6 ?+ e
san_map = folium.Map(location = [latitude, longitude], zoom_start = 12)
, q8 D$ S# D( [ ]2 a" X8 n
6 w% n3 z% ]. ?' c8 f0 l # instantiate a mark cluster object for the incidents in the dataframe
" k, z' s0 @+ t) s) X3 w
incidents = plugins.MarkerCluster().add_to(san_map)
6 F. [; @) k1 f5 k
" v# E# ^% W+ l' C/ r3 D3 P5 Z3 K # loop through the
dataframe and add each data point to the mark cluster
6 z5 v, c+ i& p \8 h
for lat, lng, label, in zip(data.Y, data.X, cdata.Category):
3 f' }7 w- c. u: O" }# C! j5 Y folium.Marker(
" N7 F/ w9 }5 f
location=[lat, lng],
/ i, U& P) u4 ]3 I
icon=None,
9 A( j' F1 f0 l" Q' R1 u
popup=label,
8 t! ~, I! E8 M2 v
).add_to(incidents)
- G7 F% q3 V) ]! z8 ^% ?+ `- H1 V
7 g: u0 L, d, W! }7 `: G
# add incidents to map
9 i- p! N7 h; i. y+ M- V( N9 O
san_map.add_child(incidents)
' ~! |5 `0 c- |5 J1 h; q1 Y5 N1 ~& n' u
' W4 U# C( z: K9 A 7. 读取geojson文件,可视化旧金山市10个不同Neighborhood的边界
3 r8 D3 d9 a& ?& ?0 ^ import json' V8 k. \0 a- N1 O) [4 g: i8 m
import requests6 T/ m2 j* K* |; S4 X# t4 x- e; L
0 o+ c: _) ]0 H: R- y( B url = https://cocl.us/sanfran_geojson
. H! w, j% N! a8 h; S/ Y; U san_geo = f{url}
4 t3 @4 L4 \3 s# f2 v san_map = folium.Map(location=[37.77, -122.4], zoom_start=12)
$ u; ]6 o0 P" p! `2 s2 W folium.GeoJson(
( b4 d2 V4 Z' c1 d9 A5 z san_geo,0 ~7 A1 q5 n, B/ u, }; ^
style_function=lambda feature: {; v* J4 N# j! p: v
fillColor: #ffff00,
2 C& c5 ~- l! |" K color: black,
) I4 c* c3 k" u4 x weight: 2,
5 Y! e8 H- W5 I# n+ ~% k3 B, q' l dashArray: 5, 5
7 [/ g! v$ x% g# J5 @1 ?; K% L }/ C# b# R1 ~. S9 Y3 `. `! ?5 N
).add_to(san_map)
! r2 m2 v! ^. b$ K2 K! L4 Y0 \1 o2 r+ s+ d( Y/ ]8 Y0 ?6 U
#display map
3 b% d2 k r2 t1 d r* y( _ san_map
" h2 X& ?9 k4 p0 ]. v
9 p6 W$ \7 E% x6 u. @3 L
8. 统计每个区域的犯罪事件数目
0 K' d( a' j% J# L
# Count crime numbers in each
neighborhood
2 t7 p+ V5 F6 K# [ disdata = pd.DataFrame(cdata[PdDistrict].value_counts())
! c8 L. K% L0 V1 l7 G
disdata.reset_index(inplace=True)
8 E, m# X. b1 d
disdata.rename(columns={index:Neighborhood,PdDistrict:Count},inplace=True)
; _! n/ _! s( o" h: R disdata
, k- G' V% m N- x Y0 S0 B& ~ " v. @- \/ ^, U6 i4 |
9. 创建Choropleth Map (颜色深浅代表各区犯罪事件数目)
: R8 ?6 x1 k d! W ^$ @* v
m = folium.Map(location=[37.77, -122.4], zoom_start=12)
8 s/ U& X, a# }8 N! P
folium.Choropleth(
, G$ g8 n$ P4 F9 ~5 Q geo_data=san_geo,
3 C* q5 n2 ?) A1 F6 H1 ]6 x data=disdata,
9 F( g1 F3 {! C+ y! v columns=[Neighborhood,Count],
( I1 z( D. Q, c2 x; j& a g
key_on=feature.properties.DISTRICT,
. q6 t4 U. _9 c5 l. l6 ]9 f
#fill_color=red,
( |6 a5 e4 W0 k( W
fill_color=YlOrRd,
8 d y3 {2 l+ Y' J5 C M fill_opacity=0.7,
/ Z/ b& o+ t: i3 }1 a$ y line_opacity=0.2,
3 X* `/ q& B( t8 Z: U highlight=True,
8 U4 a$ S6 Q0 {! ?% A
legend_name=Crime Counts in San Francisco
2 G& w( k6 n- c/ j7 F
).add_to(m)
' U2 K/ Z0 Y; w7 L/ L
m
) {9 B m% H+ `, f0 M/ B
G8 O* |; l2 I S4 p9 i * a& E4 r1 g' U2 E! T+ T
10. 创建热力图
6 o8 F# m3 b: _: i3 Z R8 \
from folium.plugins import HeatMap) K: d* A- F: `/ { D3 @ O
" Z& s% ^! f1 L4 l) ~/ ^) M- V0 K! g( m
# lets start again with a clean copy of the map of San Francisco
: e; W' Q7 Y0 q6 u! p" O san_map = folium.Map(location = [latitude, longitude], zoom_start = 12)
9 T; X( m( a* w7 A0 c8 \4 _- D/ i8 }6 h) s9 S4 ]7 t; b
# Convert data format3 ~: ~- a% H \2 r+ V8 A; ^5 L
heatdata = data[[Y,X]].values.tolist()" S- }5 I: |2 i2 b' v9 s/ j
" r, \6 |8 Q6 P3 j4 D6 P- v" @
# add incidents to map
$ Z) D+ M2 \" e" ?" J9 D HeatMap(heatdata).add_to(san_map)
) q2 i7 f) g: O: G5 G7 m5 T# z' R! Q+ ~3 n
san_map
/ c" y) B1 K6 W* m! G2 z5 p, l. J" H9 o
: T+ |2 F/ ~- {) Q: f1 f, ]9 k 最后,folium还可以用来创建动态热力图,动态路径图等,具体可参考Medium上的这篇文章。
) W; G7 [: N6 t6 y: g; N 实现效果如下图所示 (直接从Medium上抱过来的图,详细代码请点击上述链接)。
- Q/ h+ {: a/ `& ~
. W) x( t! W/ a2 W5 f 我的其他回答:
, y# M: x* i8 M+ _/ ?9 T
% t% g4 v0 X, U Z# O7 j ( R! O N, Y) }" {7 _4 j
$ I! r& f* v; a N: D0 f8 { 最近有小伙伴私信我推荐一些学习编程的经验,我给大家几点建议:
9 B0 _& u# a9 ?4 a! d! t 1. 尽量不去看那些冗长的视频教程,不是说学不到知识,而是,在你学到知识之前,你可能已经睡着了 =_=
5 E$ g: s% L. S+ \5 M
2. 不要贪多,选一个知名度高的python教程,教学为辅,练习为主。要随时记住,我们学习python的目的在于会用,而不是背过了多少知识点。
4 k9 M2 j: d7 L" Z7 x 给大家推荐一款我超喜欢的python课程——夜曲编程。我闲没事在上面刷了一些编程题目,竟回想起当年备考雅思时被百词斩支配的恐惧。这款课程对新手小白很适合。虽然有手机app,但我建议你们用网页端学习哈。
2 I6 ~$ Y9 A$ v# ~% K7 [ 最后,我的终极建议是:无论选什么教程,贪多嚼不烂,好好专注一门课程,勤加练习才是提高编程水平的王道。等基础知识学的差不多了,去Kaggle上参加几场比赛,琢磨琢磨别人的编程思路和方法就完美啦!
) b( y, b1 c y% y' n Z0 g