1. 程式人生 > >利用R包ggmap進行空間視覺化

利用R包ggmap進行空間視覺化

ggmap 是在R環境裡呼叫地圖作用視覺化的利器。它的語法結構跟ggplot2非常相似,也使R語言的使用者可以迅速上手。 ggmap 結合 ggplot 可以方便快速繪製基於地圖的視覺化圖表。下面的文章裡,我將用兩個例子 (”三藩市的犯罪記錄” 和 “Taxi in Porto“) 演示一下它的使用。案例資料均取自kaggle。

初步瞭解ggmap

  1. get_map: 是最基本的功能,可以用於從(google/openstreetmap)下載地圖。

地圖下載引數

  1. location: 如果我們知道資料的準確經緯度,我們可以直接使用。或者我們可以直接用geocode. (如 ‘San Francisco’ 用表示三藩市)
  2. maptype: 可以根據視覺化的需要,選擇 ‘terrain’, ‘satellite’, ‘roadmap’, ‘hybrid’, 通常“terrain”就可以達到不錯的效果。
  3. zoom: 可以選擇從 3 (大陸範圍) 到 21 (建築物範圍). 因為這裡的例子都是針對城市,所以我選擇10-14 (城市範圍)
  4. ggmap: 用作繪製地圖,可以和ggplot疊加

舊金山的犯罪記錄

這組資料 包含了舊金山從2013年至2015年的各種犯罪記錄有及發生地點。讓我以2014年的資料做以下的視覺化演示。

瞭解資料

這裡我們只需要使用犯罪的類別(Category),經度(X),緯度(Y)

head(data_2014[c('Category'
,'DayOfWeek','PdDistrict','X','Y','Year')])
##            Category DayOfWeek PdDistrict         X        Y Year
## 27585 LARCENY/THEFT    Sunday    MISSION -122.4356 37.76080 2014
## 27586 LARCENY/THEFT    Sunday   NORTHERN -122.4336 37.80004 2014
## 27587 VEHICLE THEFT    Sunday    CENTRAL -122.4128 37.78683 2014
## 27588 ASSAULT Sunday NORTHERN -122.4217 37.77364 2014 ## 27589 ASSAULT Sunday NORTHERN -122.4217 37.77364 2014 ## 27590 ASSAULT Sunday NORTHERN -122.4217 37.77364 2014

發生最為頻繁的是Larceny, other offences, non-criminal, assault and vehicle theft, 然而在這些的類別裡面other offences and non criminal並不能給我們帶來太多資訊。因此,我會在地圖上顯示Larceny, Assault and Vehicle Theft,這三種犯罪的空間密度。

Crime=data.frame(table(data_2014$Category))
Crime=Crime[order(Crime$Freq,decreasing=T),]
head(Crime)
##              Var1  Freq
## 17  LARCENY/THEFT 18901
## 22 OTHER OFFENSES 10290
## 21   NON-CRIMINAL  9669
## 2         ASSAULT  6254
## 35  VEHICLE THEFT  3564
## 34      VANDALISM  3538

地圖下載和繪製

Use ggmap to plot the map and use geom_jitter to plot the crimes in San Francisco:
使用get_map語句下載得到舊金山市區的地圖。

library(ggmap)
map=get_map(location='San Fransico',maptype='roadmap',zoom=12)
## Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=San+Fransico&zoom=12&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false

使用ggmap語句繪製地圖,geom_jitter畫化不互相疊加的點,以表示每個犯罪的發生。

plot_crime <- ggmap(map)+geom_jitter(aes(X,Y,colour=Category),
  data=data_2014[data_2014$Category %in% Top3,],alpha=0.2)+geom_jitter(aes(X,Y,colour=Category),
    data=data0[data0$Category %in% Top3,],alpha=1)+labs(x='Longitude',y='Latitude')
plot_crime

plot of chunk unnamed-chunk-3

一些發現

在2014年裡,Larceny/Theft (綠色)的案件要遠遠多過別的犯罪事件。大多數的犯罪發生在北海岸。
The assault crimes (紅色)主要集中發生在 Tenderloin, 而該地區就是舊金山一個知名的high-crime neighbourhood
The Vehicle theft crime (藍色) 的發生率比起前兩種要少很多,沒有特別嚴重的地區。

波爾圖的計程車

這組資料 包含了波爾圖計程車的位置軌跡資訊。波爾圖為葡萄牙的第二大城市。

瞭解資料

head(test[c('TRIP_ID','TAXI_ID','TIMESTAMP','DAY_TYPE','MISSING_DATA')])
##   TRIP_ID  TAXI_ID  TIMESTAMP DAY_TYPE MISSING_DATA
## 1      T1 20000542 1408039037        A        False
## 2      T2 20000108 1408038611        A        False
## 3      T3 20000370 1408038568        A        False
## 4      T4 20000492 1408039090        A        False
## 5      T5 20000621 1408039177        A        False
## 6      T6 20000607 1408037146        A        False

在這裡,我將只使用POLYLIN列的資料(計程車的運動軌跡)。這裡我們定義POLYLIN的第一個位置為上客點,最後一個位置為下客點。

資料預處理

test$POLYLINE[1]
## [1] "[[-8.585676,41.148522],[-8.585712,41.148639],[-8.585685,41.148855],[-8.58573,41.148927],[-8.585982,41.148963],[-8.586396,41.148954],[-8.586072,41.14872],[-8.586324,41.147847],[-8.586999,41.14746],[-8.586576,41.147154],[-8.584884,41.146623]]"
getCoord=function(x){
  x=gsub('[/[]','',x)
    x=gsub(']','',x)
    x=strsplit(x,',')[[1]]
    n=length(x)
    lon=as.numeric(x[seq(1,n,2)])
    lat=as.numeric(x[seq(2,n,2)])
    df=data.frame(lon=lon,lat=lat)
    df$status='moving'
    df$status[1]='pickup'
    df$status[nrow(df)]='dropoff'
    return(df)
}

通過一些處理,我們可以從POLYLINE資料中,提取經緯度,以及計程車的運動狀態。

loc=NULL
for (i in 1:length(polyline)){
  loc=rbind(loc,getCoord(polyline[i]))
}
head(loc)
##         lon      lat status
## 1 -8.585676 41.14852 pickup
## 2 -8.585712 41.14864 moving
## 3 -8.585685 41.14885 moving
## 4 -8.585730 41.14893 moving
## 5 -8.585982 41.14896 moving
## 6 -8.586396 41.14895 moving

運用同樣的方法, 我們用ggmap畫出波爾圖的城市地圖以及計程車的運動軌跡。

library(ggmap)
map=get_map(location=c(lon=median(loc$lon),lat=median(loc$lat)),
  maptype='roadmap',zoom=13)
## Map from URL : http://maps.googleapis.com/maps/api/staticmap?center=41.161833,-8.612033&zoom=13&size=640x640&scale=2&maptype=roadmap&language=en-EN&sensor=false
plot_taxi=ggmap(map)+labs(x='Longitude',y='Latitude')+
geom_jitter(aes(lon,lat,colour=factor(status)),data=loc[loc$status=='moving',],alpha=0.4)+
geom_point(aes(lon,lat,colour=factor(status)),data=centers,size=10,alpha=0.6)+
geom_jitter(aes(lon,lat,colour=factor(status)),data=loc[loc$status!='moving',],alpha=0.8)
plot_taxi

plot of chunk unnamed-chunk-7

一些發現

我從未去過葡萄牙,但是我也可以猜到Vitoria是商業中心或者是風景名勝,因為計程車的在那裡的運動密度特別大。
我們發現在東北和西北有兩個主要的上客和下客地點,推測可能是居住的密集區。如果你注意到圖中幾個大的點,那是用kmeans聚類的上下客的地點。

the completed R code is available: here, if you are interested to check out.