8 v" g' W2 S% |: A- ` o 推荐一个超好用的python包folium, 专门用于地理数据可视化,官方英文教程教程点击这里。
7 E3 I( E, i @; j * m( X; g8 k; H5 F5 R: R
使用方法很简单,操作如下:
导入包,创建一副世界地图- _3 j) v, n: G9 f& G! ~8 t
import folium5 t7 p2 `0 \1 _6 m
import pandas as pd2 f I* }- Z& N- Z) @
! H, `. b$ W3 f6 i" y1 ~3 t2 X # define the world map% H4 P. o+ l! v! J7 R: \: q
world_map = folium.Map()0 w6 c( t$ S D5 A
% E) t6 {" O2 e5 ^ # display world map
# f [) }) m% W) A world_map
+ a, `' |% O5 P- x# K 3 I9 c& Y2 h) R
2. 输入经纬度,尺度,在这里我们以旧金山(37.7749° N, 122.4194° W)为例。
4 a# A+ p, x c" ]5 i) p* r; Y # San Francisco latitude and longitude values: g/ h y/ `9 J7 _* F0 e- L% }
latitude = 37.77
2 P4 f1 d. d5 C J4 H# H longitude = -122.42
2 P3 v: H Z. ~ d* r+ j1 n6 N# q) D8 Z9 S% V
# Create map and display it2 H- {. G( u4 w; S7 N) {" x- J
san_map = folium.Map(location=[latitude, longitude], zoom_start=12)
0 H8 C/ O. z' c6 k- f$ |& Y1 s
/ v( H( z1 Y3 Q9 M/ R8 Z # Display the map of San Francisco1 {# R9 o& Q. c: O
san_map
+ e5 q1 M4 F' G7 X. P
: K6 P' S2 |5 j8 {. b2 B" _+ W- M1 x 更改地图显示,默认为OpenStreetMap风格,我们还可以选择Stamen Terrain, Stamen Toner等。
! c% p; h. |1 S) {- E
# Create map and display it
& m* H3 d: a, R$ E san_map = folium.Map(location=[latitude, longitude], zoom_start=12,tiles=Stamen Toner)
1 H$ @0 F3 d: N0 [
8 n. }- y6 v1 }! B4 T
3. 读取数据集(旧金山犯罪数据集)
6 T, g; u8 }2 |
# Read Dataset
" S" r7 i1 H. E A cdata = pd.read_csv(https://cocl.us/sanfran_crime_dataset) Y8 q( E" C# V5 v8 L9 j
cdata.head()
/ w) O' n. }/ \' W
# b. s% R# v8 ]1 E) k 4. 在地图上显示前200条犯罪数据
5 j8 r9 l: N3 R9 h
# get the first 200 crimes in the cdata
/ I [# l) }' R# |4 d+ x
limit = 200
4 h: S$ b' @5 {5 b9 i1 G
data = cdata.
iloc[0:limit, :]
; A/ i4 A0 _4 ^( \: A. I! B
, U/ S+ }7 l- k4 v+ h, _
# Instantiate a feature group for the incidents in the dataframe
% O* n) z! z: G7 `0 C+ V
incidents = folium.map.FeatureGroup()
* ~- r/ `; T' g# b' K
6 v# G7 Q+ y2 O3 j # Loop through the 200 crimes and add each to the incidents feature group
* Q4 _0 m. b1 F/ i7 Y% n# k for lat, lng, in zip(cdata.Y, data.X):
1 U; @; C' Q2 z) `$ j incidents.add_child(
& Y+ Z) S% H1 W, t1 z/ S4 Z! j# b folium.CircleMarker(
9 B" S& I% k# O M/ o: Q [lat, lng],
% h/ X' O/ e7 `7 o& o. f3 n radius=7, # define how big you want the circle markers to be
3 b) L- e: y# t4 v, D- e
color=yellow,
Q3 d" h2 O5 z N0 U: q fill=True,
9 P6 E8 R: N9 T" d- o+ a
fill_color=red,
" i: ]% m* q& S- _! K fill_opacity=0.4
9 H, m5 f, `5 N. B9 ^
)
3 ?$ r: d8 t* v* e$ y
)
$ v, m6 h) d+ b* M; |1 h7 y9 G1 M5 V0 Z6 U( B% X* ~4 v: g
# Add incidents to map
o& w7 `* ~" ?0 g san_map = folium.Map(location=[latitude, longitude], zoom_start=12)
5 I9 j [% R/ I. r/ Q9 u5 e san_
map.add_child(incidents)
$ c+ }7 G& u# B; s
5 ~. S5 p P1 L 5. 添加地理标签
( X( W* L5 Q! c( F$ V # add pop-up text to each marker on the map
- l4 w' A* m7 t/ W9 [' h! w
latitudes = list(data.Y)
7 ~+ _6 n! S. f
longitudes = list(data.X)
- M2 G( K7 Y. m* q5 ], f labels = list(data.Category)
$ P6 W! I( S5 Z2 A
z3 j- w1 R5 L" l3 H for lat, lng, label in zip(latitudes, longitudes, labels):
1 ^/ o' O3 {0 J' f; H' M folium.Marker([lat, lng], popup=label).add_to(
san_map)
/ F% W& ?& b$ V3 L0 J- ?% c/ O
( H" z% X1 |5 W
# add incidents to map
2 o8 t7 h6 Y3 y: E. t, h' W- x; t san_map.add_child(incidents)
9 }' S& f4 x _3 D$ ]8 t# |
5 ~ f' j1 c% W3 R! b' s 6. 统计区域犯罪总数
4 U4 ]& w$ B6 X" }, J from folium import plugins
; M; P# @1 b& ?+ x. x( ?4 ^7 |2 Y1 z$ c+ C4 P, S7 k5 Z
# lets start again with a clean copy of the map of San Francisco
' }: [1 v8 [$ b' @1 ]; ^ san_map = folium.Map(location = [latitude, longitude], zoom_start = 12)
3 h- ^' L1 h3 V3 H) V# s: P
; y3 {, u! Y& S # instantiate a mark cluster object for the incidents in the dataframe
2 t" t$ B( }* ~1 s incidents = plugins.MarkerCluster().add_to(san_map)
6 d, G8 \- [0 @- q$ K; L. B
1 M: j$ l, O" w) b% ~
# loop through the
dataframe and add each data point to the mark cluster
* K3 j0 p, @: ?+ ?1 s+ u6 ^& F
for lat, lng, label, in zip(data.Y, data.X, cdata.Category):
$ ~3 V- n' ^# t folium.Marker(
h. @5 i( y: U0 e+ Y* \& h
location=[lat, lng],
& Q/ W, g/ j+ b( Q icon=None,
5 k; D) j: T7 A( _
popup=label,
3 u$ C# f: S1 J2 m, g1 ~3 a& n ).add_to(incidents)
# x& r' p: Q! H* |, ^
" z9 {/ D4 d" {( k4 x7 S) i # add incidents to map
. m; e; r9 G4 a/ K
san_map.add_child(incidents)
5 Q9 Y$ V4 L" t; A5 n1 ~
' b8 D- ]" R3 T! Z) ~8 ~
7. 读取geojson文件,可视化旧金山市10个不同Neighborhood的边界
, q3 C6 _- l7 [) h
import json
3 }0 m. L) ?2 L8 ^; Y import requests% u- v2 z. M* Z
0 ^, |, w* [$ o- l9 T
url = https://cocl.us/sanfran_geojson
, u) p2 Q+ h9 ]9 ~. _ san_geo = f{url}
2 C+ |& C* D/ U5 I' c san_map = folium.Map(location=[37.77, -122.4], zoom_start=12)
: n3 {* Q( U: p1 `, j folium.GeoJson(
m/ E/ _" ^& {# q8 z' F) p0 a9 } san_geo,
( O" L, ?4 X2 m5 m0 R style_function=lambda feature: {
( Q( d6 t! m3 F; u5 v& `8 C5 L0 r" ^ fillColor: #ffff00,' [" T, J n n; p- P; R$ |% r; U- b m
color: black,5 y& s* b _8 e q
weight: 2,; `( V: q& ~: Y9 _! Z$ V" _" E
dashArray: 5, 59 w/ M9 U" T$ |4 K6 }2 N
}6 V. r) X X$ ^/ T0 M: d
).add_to(san_map)/ A9 _# C* r4 _/ l4 G7 N. t
/ B( h" n. P4 R9 m7 T
#display map
$ ?. Z, M, M9 P+ q7 f- c san_map
- O, B! l; _) W5 g( ` G# s0 L v * h) C2 |' X8 a
8. 统计每个区域的犯罪事件数目
4 u4 ^* t' L Y
# Count crime numbers in each
neighborhood
0 I9 ?* a* E# b- w disdata = pd.DataFrame(cdata[PdDistrict].value_counts())
8 Z& j3 {$ L) F) g) W4 D: x
disdata.reset_index(inplace=True)
! @$ z# V( Y G& g9 T, }8 X# m disdata.rename(columns={index:Neighborhood,PdDistrict:Count},inplace=True)
( a: E9 p2 Z& O, C! k
disdata
; i) }; v" I9 x8 d9 K+ Q
5 Y6 r4 H7 m7 v. |" Q; K/ g
9. 创建Choropleth Map (颜色深浅代表各区犯罪事件数目)
, q2 z6 g8 i0 `6 |8 k m = folium.Map(location=[37.77, -122.4], zoom_start=12)
: |8 K9 |1 ?2 U folium.Choropleth(
6 O! b) A7 i' g" v geo_data=san_geo,
( |7 F/ T! c3 w
data=disdata,
0 u9 M6 y; H* P
columns=[Neighborhood,Count],
1 I) j3 R+ C# J. U) [
key_on=feature.properties.DISTRICT,
( Y. f6 A* v/ W8 r #fill_color=red,
* Y; \2 d6 ]- ?2 | fill_color=YlOrRd,
( W; s% D+ }* _: _; y
fill_opacity=0.7,
: ?5 n6 g* [, |1 _* X! G
line_opacity=0.2,
' I" C a. d6 B9 J9 d0 q( j
highlight=True,
) H+ _: q) x& K# R: v
legend_name=Crime Counts in San Francisco
( V K+ W! p- i! t
).add_to(m)
5 Q) f: S& S W$ i+ }# i/ R/ W
m
% _$ `& {, Z' O; [& |# L + J6 @( |' ]5 z) l+ d+ P
3 J* A' z1 n1 { K6 f
10. 创建热力图
8 o9 }3 Z7 T+ d& p; p- |8 f6 ]
from folium.plugins import HeatMap
# ?; v: H6 F! S8 b3 X$ Q
& B) t6 j6 g+ O # lets start again with a clean copy of the map of San Francisco. `4 C G( c4 |: R
san_map = folium.Map(location = [latitude, longitude], zoom_start = 12)
A( y7 Y6 w( K' Z, J: C$ ^( m( l% r* w2 a5 K/ c% a1 }
# Convert data format
8 o: x, q, g1 ?% Y2 D- I heatdata = data[[Y,X]].values.tolist()- Z- _, C' W0 I% C
% {6 T$ T4 Q. p8 Y" _& y
# add incidents to map9 @- J' t% ?; M9 p
HeatMap(heatdata).add_to(san_map)
. P0 ^% { V, w- N! `1 C" _! L4 C6 s
* {9 X4 a/ V% q" Y$ o/ I san_map
( Y' ^# ?, b2 h4 x/ y. b " t) m" b* E' P, A1 b ]
最后,folium还可以用来创建动态热力图,动态路径图等,具体可参考Medium上的这篇文章。
4 M1 Y' h) p0 H F1 w$ }' Z 实现效果如下图所示 (直接从Medium上抱过来的图,详细代码请点击上述链接)。
' F6 D) y# W {% v
$ ?5 L# o1 ?% {/ G$ | 我的其他回答:
: J% e/ b# |8 \2 b! L! J' l
- d7 T9 M5 o+ p: a9 { . |) f0 _- @0 h+ O
6 V4 @( v; q- Y& C' f1 x 最近有小伙伴私信我推荐一些学习编程的经验,我给大家几点建议:
0 B1 U Q4 t" [6 W
1. 尽量不去看那些冗长的视频教程,不是说学不到知识,而是,在你学到知识之前,你可能已经睡着了 =_=
/ c/ b2 ?% `9 }/ H8 L' |+ [( G" c5 E 2. 不要贪多,选一个知名度高的python教程,教学为辅,练习为主。要随时记住,我们学习python的目的在于会用,而不是背过了多少知识点。
- E. w3 \9 F) @" t; b3 y 给大家推荐一款我超喜欢的python课程——夜曲编程。我闲没事在上面刷了一些编程题目,竟回想起当年备考雅思时被百词斩支配的恐惧。这款课程对新手小白很适合。虽然有手机app,但我建议你们用网页端学习哈。
! Y, \2 F" K0 [+ G, z
最后,我的终极建议是:无论选什么教程,贪多嚼不烂,好好专注一门课程,勤加练习才是提高编程水平的王道。等基础知识学的差不多了,去Kaggle上参加几场比赛,琢磨琢磨别人的编程思路和方法就完美啦!
6 T" n! I& m& `( o8 }