ggmap:使用ggplot2進行空間可視化繪圖(中篇)

作者:戴維 · 卡爾&哈德利·威克姆

翻譯:李博

原文地址:ggmap: Spatial Visualization with ggplot2

PS:由於原文較長,故翻譯分為三次進行。

06.ggmap 函數

只要get_map抓取了有意思的地圖,ggmap就可以繪製了。get_map抓取的結果是一個特殊類別的柵格(raster)對象(一個十六進位字元串的顏色矩陣)

paris <- get_map(location = "paris")nstr(paris)nqmap(baylor, zoom = 14, maptype = 53428, api_key = api_key,nsource = "cloudmade")nqmap("houston", zoom = 10, maptype = 58916, api_key = api_key,nsource = "cloudmade")nnchr [1:1280, 1:1280] "#C6DAB6" "#C2D6B3" "#C2D6B3" ...n- attr(*, "class")= chr [1:2] "ggmap" "raster"n- attr(*, "bb")=』data.frame』: 1 obs. of 4 variables:n..$ ll.lat: num 48.6n..$ ll.lon: num 1.91n..$ ur.lat: num 49.1n..$ ur.lon: num 2.79n

圖6:兩千萬用戶製作的CloudMade地圖樣式。左圖與圖3和圖5相當,右圖包含圖4中的水域。(圖1—圖5,參考上篇)

以下為個人加入內容(代碼):

##下面的地址鏈接表明了圖片的位置n> paris <- get_map(location = "paris")nMap from URL : http://maps.googleapis.com/maps/api/staticmap?center=paris&zoom=10&size=640x640&scale=2&maptype=terrain&language=en-EN&sensor=falsenInformation from URL : http://maps.googleapis.com/maps/api/geocode/json?address=paris&sensor=falsen> str(paris)#這裡需要掌握str()函數的用法,即用於緊湊的顯示任意R對象結構n chr [1:1280, 1:1280] "#CBE5A2" "#CBE5A2" "#C8E3A1" "#C8E3A1" "#C8E09D" "#C3DD9D" ...n - attr(*, "class")= chr [1:2] "ggmap" "raster"n - attr(*, "bb")=data.frame: 1 obs. of 4 variables:n ..$ ll.lat: num 48.6n ..$ ll.lon: num 1.91n ..$ ur.lat: num 49.1n ..$ ur.lon: num 2.79n - attr(*, "source")= chr "google"n - attr(*, "maptype")= chr "terrain"n - attr(*, "zoom")= num 10n>n

ggmap的目的是把地圖從柵格對象中輸出到屏幕,並通過創建一個ggplot對象來實現這一目的。圖像列印時,在圖形設備中繪製所需的地圖。如圖7所示。

圖7

而ggmap需要一個ggmap對象,它接受一小部分參數——範圍,底圖(base_layer),距離(maprange),圖例,填充和亮度。

若無這些附加參數,則ggmap有效返回以下ggplot對象。

ggplot(aes(x = lon, y = lat), data = fourCorners) +ngeom_blank() + coord_map("mercator") +nannotation_raster(ggmap, xmin, xmax, ymin, ymax)n

其中fourCorners是,將expand.grid應用於ggmap對象的bb屬性中,並指定的經緯度範圍產生的數據集。因此,由ggmap創建的ggplot2對象的默認底圖(即原始畫框)是,ggplot(aes(x = lon,y = lat),data = fourCorners),默認的x、y軸是根據地圖的緯度範圍計算而來。

範圍參數指定地圖覆蓋了多少圖形範圍。它接受三個字元串:圖7所示的「normal(標準)」,圖10和圖12所示的「panel(面板)」和每個圖中所示的「device(圖案)」。

「normal」通過ggplot2提供默認坐標來定位地圖,因此可以看到它後面的面板。 「panel」則將繪圖面板的極限設置為scale_ [x,y] _continuous(expand = c(0,0)))的地圖的經緯度範圍。而「device」則通過使用新的theme_nothing命令,將這一功能用到了極致。

base_layer是一個將默認基本層替換為用戶要求的命令。因此,在上述代碼中,用戶可以將ggplot(aes(x = lon,y = lat),data = fourCorners)更改為不同的命令。由於ggplot2函數中facet_wrap和facet_grid處於基礎層,因此這對於 faceting plots(局部小塊繪圖)非常重要。

同時,由於更改基本層會改變基本尺度並因此改變繪圖的範圍,所以當基本層改變時,只有部分地圖可見。將maprange參數設置為TRUE(默認為FALSE),並通過ggmap對象本身的bb屬性確定x和y軸(經度和緯度),而不是base_layer參數。

ggmap(paris, extent = "normal")n

圖7:在ggmap中設置extent =「normal」,說明ggmap中的地圖和ggplot2繪製圖形的相似性。

ggmap有關說明性的參數是圖例和填充,它們只適用於extent =「device」。圖例參數確定了在地圖上繪製圖例的位置。它的選項是「left」,「right」(默認),「bottom」,「top」,「topleft」,「bottomleft」,「topright」,「bottomright」和「none」。

前四個根據ggplot2的標準規格(沒有任何軸)繪製圖例;後四個繪製地圖上的圖例就像ArcGIS(一個可伸縮的,全面的GIS平台)一樣;最後的「none」用於減去圖例。填充控制主要是定義圖例應該繪製在距離邊角多遠的地方。

亮度參數,是由Jean-Olivier Irisson提出的一個建議,用於調整圖像色彩。默認值c(0,「black」)表示完全半透明的黑色層,即完全沒有色彩。

通常情況下,第一個參數對應於alpha混合(0 =不可見(invisible),1 =不透明(opaque)),第二個參數是色調的顏色。如果只有一個數字被提供給ggmap(假定一個黑色色彩的亮度參數),色調本身是通過在地圖的上添加一個geom_rect層來製作的。圖2提供了一個例子,其中黑色色彩被添加到地圖以增強點的可視性。

由於ggmap返回一個ggplot對象,ggmap的輸出本身可以作為ggplot2框架中的基礎層。這是一個非常難得的重要的實現——它允許ggplot2的全部功能。我們現在通過在德克薩斯州休斯頓市中心的一個暴力犯罪案例研究來說明這些方法的有效性 。

07.ggmap實踐

數據data

犯罪數據是由休斯頓警察局的網站,在2010年1月至 8月期間彙編的。使用plyr(韋翰,2011年)對這些數據進行了輕微的清理和匯總,同時使用了谷歌地圖的地理編碼;因此,完整的數據在ggmap中可用來作為犯罪數據集。

> str(crime)n』data.frame』: 86314 obs. of 17 variables:n$ time : POSIXt, format: "2010-01-01 0...n$ date : chr "1/1/2010" "1/1/2010" "1...n$ hour : int 0 0 0 0 0 0 0 0 0 0 ...n$ premise : chr "18A" "13R" "20R" "20R" ...n$ offense : chr "murder" "robbery" "aggr...n$ beat : chr "15E30" "13D10" "16E20" ...n$ block : chr "9600-9699" "4700-4799" ...n$ street : chr "marlive" "telephone" "w...n$ type : chr "ln" "rd" "ln" "st" ...n$ suffix : chr "-" "-" "-" "-" ...n$ number : int 1 1 1 1 1 1 1 1 1 1 ...n$ month : Factor w/ 12 levels "january"...n$ day : Factor w/ 7 levels "monday" ...n$ location: chr "apartment parking lot" ...n$ address : chr "9650 marlive ln" "4750 ...n$ lon : num -95.4 -95.3 -95.5 -95.4 ...n$ lat : num 29.7 29.7 29.6 29.8 29.7...n

由於我們只對在市中心發生的暴力犯罪感興趣,所以我們需要對數據進行一些設置限定。首先要確定一個地理位置的邊界,使用gglocator,一個ggmap輸出的類似於定位的函數ggplot2。 gglocator不僅用於ggmap繪圖,而且可用於一般的ggplot2製圖。

##原文如下n> # find a reasonable spatial extent(找到一個合理的空間範圍)n> qmap(』houston』, zoom = 13)n> gglocator(2)n> lon latn> 1 -95.39681 29.78400n> 2 -95.34188 29.73631n>n> # only violent crimes(僅限暴力犯罪)n> violent_crimes <- subset(crime,n+ offense != "auto theft" & offense != "theft" & offense != "burglary")n>n> # order violent crimes(攻擊性暴力犯罪)n> violent_crimes$offense <- factor(violent_crimes$offense,n+ levels = c("robbery", "aggravated assault", "rape", "murder"))n>n> # restrict to downtown(市中心範圍)n> violent_crimes <- subset(violent_crimes,n+ -95.39681 <= lon & lon <= -95.34188 &n+ 29.73631 <= lat & lat <= 29.78400)n

分析只涉及嚴重傷害襲擊,搶劫,強姦和謀殺的暴力犯罪數據。請注意,儘管為確保數據的質量做出了一些努力,但是數據還是被輕微清理,同時數據集可能仍然包含錯誤。

08.分析

第一步,我們能做的是看看個體犯罪發生的地方。通過模擬一些簡單的ggplot2類型(主要是通過ggplot2具有導向功能的圖例字體和鍵型),圖8左側包含生成顯示空間氣泡圖的代碼。

泡泡圖的其中一個問題是圖的重疊和點的大小,我們不能依靠感覺去確定犯罪的發生地。

處理這一問題的一個方法是將點分開,並剔除沒有任何樣本的點。(圖8右圖)向我們展示了犯罪行為的發生情況。

圖8:休斯頓市中心的暴力犯罪泡泡圖(左)和同樣的箱圖(右)

theme_set(theme_bw(16))nHoustonMap <- qmap("houston", zoom = 14, color = "bw", legend = "topleft")nHoustonMap +ngeom_point(aes(x = lon, y = lat, colour = offense, size = offense),ndata = violent_crimes)nHoustonMap +nstat_bin2d(naes(x = lon, y = lat, colour = offense, fill = offense),nsize = .5, bins = 30, alpha = 1/2,ndata = violent_crimesn)n

這個箱圖是我們第一次開始在ggplot2框架中看到地圖的情況。雖然它實際上並不是一個非常好的繪圖,但它在說明ggplot2框架與地圖的上下文信息中有很大優勢 ——根據犯罪變數將數據框架暴力行為劃分為塊的過程,將每個地點的點數匯總到一個數據集,繪圖最後由ggplot2在幕後完成。

那麼,一般暴力犯罪怎麼辦?如果我們忽略了犯罪的類型,我們可以通過使用輪廓圖來了解暴力犯罪的空間分布。由於地圖圖像本身是基於ggplot2的annotation_raster,它沒有繪製坐標,但我們可以訪問添加的坐標,以形成一個填充的輪廓圖。這在圖9中看到(左圖)。

圖9:暴力犯罪的輪廓圖(左),加入一個小插圖(右圖右下角)。

houston <- get_map("houston", zoom = 14)nHoustonMap <- ggmap("houston", extent = "device", legend = "topleft")nHoustonMap +nstat_density2d(naes(x = lon, y = lat, fill = ..level.., alpha = ..level..),nsize = 2, bins = 4, data = violent_crimes,ngeom = "polygon"n)noverlay <- stat_density2d(naes(x = lon, y = lat, fill = ..level.., alpha = ..level..),nbins = 4, geom = "polygon",ndata = violent_crimesn)nHoustonMap + overlay + inset(ngrob = ggplotGrob(ggplot() + overlay + theme_inset()),nxmin = -95.35836, xmax = Inf, ymin = -Inf, ymax = 29.75062n)n

這種類型疊加圖是非常有效,然而,他們傳達信息的能力可能受到阻礙,即疊加圖與地圖本身存在的視覺混淆。這在使用彩色地圖時尤其常見。

為了解決這個問題,插圖功能可以用於在白色背景上插入包含疊加層的地圖插圖,輔助軸線用於theme_inset函數實現的圖例說明。這在圖9(右圖)中可以明顯看到。

同時,該圖像表明有三個主要的熱點活動。這三個中的每一個對應於休斯敦人經常活動且特別危險的地點。

從東到西,熱點是由(1)一個縣監獄,每天釋放囚犯兩次,大量的囚犯在該區域活動,(2)在大量無家可歸和貧困地區的商業公交車站, 3)一個賣淫窩點,處在城市繁華步行街地區。

除了單個圖,ggmap或qmap的base_layer參數允許小面繪圖(見圖10)。

houston <- get_map(location = "houston", zoom = 14, color = "bw",nsource = "osm")nHoustonMap <- ggmap(houston, base_layer = ggplot(aes(x = lon, y = lat),ndata = violent_crimes))nHoustonMap +nstat_density2d(aes(x = lon, y = lat, fill = ..level.., alpha = ..level..),nbins = 5, geom = "polygon",ndata = violent_crimes) +nscale_fill_gradient(low = "black", high = "red") +nfacet_wrap(~ day)n

圖10:按天形成小型輪廓圖

這對於具有離散時間分量(日,月,季度,年等)的空間數據特別有用。

最後一個繪圖顯示ggplot2中輪廓線的問題之一 ——「剪切」或「撕裂」的輪廓。除了這個直觀現象(這可能在後續的ggplot2版本中可能會被修正),我們可以看到,實際上大多數暴力犯罪發生在星期一,其次是星期五。星期五的小圖很容易解釋——在市中心的酒吧區有一個小圓點,在西南部較大地區,夜生活較為活躍。而星期一的小圖不是很容易解釋。

(未完待續)......


推薦閱讀:

對《柯嬌燕再次回應鐘焓:第二句話》惠男譯文的一些修訂
我們所閱讀的外文翻譯過來的詩是不是在一定程度上喪失了原作的美感和寓意?
不按常理出牌的英文倍數表達,你還要將錯就錯嗎?
三分鐘看懂中國網路小說紅遍世界

TAG:R编程语言 | 大数据 | 翻译 |