2017-09-18 21 views
6

Một hình ảnh đáng giá ngàn lời nói: Data does not match geometryLàm thế nào để tham gia dữ liệu và hình học đúng cách sử dụng ggmap

hành vi quan sát được: Như có thể thấy từ hình trên, tên nước không phù hợp với hình học thực tế của họ .

Hành vi mong muốn: Tôi muốn tham gia đúng khung dữ liệu với hình dạng của nó và hiển thị kết quả bằng ggmap.

Trước đây tôi đã tham gia các khung dữ liệu khác nhau, nhưng mọi thứ bị sai bởi thực tế là dường như ggmap cần "củng cố" (thực sự tôi không biết dữ liệu thực sự có nghĩa là gì) để hiển thị kết quả.

Đây là những gì tôi đã thực hiện cho đến nay:

library(rgdal) 
library(dplyr) 
library(broom) 
library(ggmap) 

# Load GeoJSON file with countries. 
countries = readOGR(dsn = "https://gist.githubusercontent.com/ccamara/fc26d8bb7e777488b446fbaad1e6ea63/raw/a6f69b6c3b4a75b02858e966b9d36c85982cbd32/countries.geojson") 

# Load dataframe. 
df = read.csv("https://gist.githubusercontent.com/ccamara/fc26d8bb7e777488b446fbaad1e6ea63/raw/a6f69b6c3b4a75b02858e966b9d36c85982cbd32/sample-dataframe.csv") 

# Join geometry with dataframe. 
countries$iso_a2 = as.factor(countries$iso_a2) 
[email protected] = left_join([email protected], df, by = c('iso_a2' = 'country_code')) 

# Convert to dataframe so it can be used by ggmap. 
countries.t = tidy(countries) 

# Here's where the problem starts, as by doing so, data has been lost! 

# Recover attributes' table that was destroyed after using broom::tidy. 
[email protected]$id = rownames([email protected]) # Adding a new id variable. 
countries.t = left_join(countries.t, [email protected], by = "id") 

ggplot(data = countries.t, 
     aes(long, lat, fill = country_name, group = group)) + 
    geom_polygon() + 
    geom_path(colour="black", lwd=0.05) + # polygon borders 
    coord_equal() + 
    ggtitle("Data and geometry have been messed!") + 
    theme(axis.text = element_blank(), # change the theme options 
     axis.title = element_blank(), # remove axis titles 
     axis.ticks = element_blank()) # remove axis ticks 

Trả lời

1

Có lý do cho hành vi sai lầm.

countries bắt đầu như một SpatialPolygonsDataFrame lớn với yếu tố (và tương ứng 177 hàng trong [email protected]). Khi bạn thực hiện left_join trên [email protected]df, số lượng phần tử trong countries không bị ảnh hưởng, nhưng số lượng hàng trong [email protected] tăng lên .

Fortifying countries sử dụng broom::tidy chuyển đổi countries, với 177 phần tử của nó, vào một khung dữ liệu với id chạy từ 0 đến 176. (Tôi không chắc chắn lý do tại sao nó là zero-lập chỉ mục, nhưng tôi thường thích để xác định các khu vực rõ ràng nào).

Thêm id-[email protected] dựa trên rownames([email protected]), mặt khác, kết quả trong id giá trị chạy 1-210, vì đó là số lượng hàng trong [email protected] sau khi trước đó tham gia với df. Do đó, mọi thứ không đồng bộ.

Hãy thử như sau thay vì:

# (we start out right after loading countries & df) 

# no need to join geometry with df first 

# convert countries to data frame, specifying the regions explicitly 
# (note I'm using the name column rather than the iso_a2 column from [email protected]; 
# this is because there are some repeat -99 values in iso_a2, and we want 
# one-to-one matching.) 
countries.t = tidy(countries, region = "name") 

# join with the original file's data 
countries.t = left_join(countries.t, [email protected], by = c("id" = "name")) 

# join with df 
countries.t = left_join(countries.t, df, by = c("iso_a2" = "country_code")) 

# no change to the plot's code, except for ggtitle 
ggplot(data = countries.t, 
     aes(long, lat, fill = country_name, group = group)) + 
    geom_polygon() + 
    geom_path(colour="black", lwd = 0.05) + 
    coord_equal() + 
    ggtitle("Data and geometry are fine") + 
    theme(axis.text = element_blank(), 
     axis.title = element_blank(), 
     axis.ticks = element_blank()) 

enter image description here

tái bút: Bạn thực sự không cần gói ggmap cho việc này. Chỉ gói ggplot2 mà nó tải.

+0

Cảm ơn bạn đã giải thích tuyệt vời! Giải pháp của bạn hoạt động tuyệt vời! Có cái gì đó tôi không hiểu mặc dù (ngay cả sau khi đã kiểm tra '? Chổi :: gọn gàng'): Có vẻ như với tôi rằng tuyên bố 'countries.t = tidy (quốc gia, khu vực =" tên ")' là chìa khóa trong câu trả lời của bạn, nhưng tôi không hiểu chính xác 'region =" name "' là gì, mặc dù tôi đã quan sát thấy sự khác biệt đáng chú ý trong đầu ra nếu tôi chỉ nhập 'countries.t = tidy (countries)' – ccamara

+0

Và cảm ơn vì đã chỉ ra rằng ggmap là không cần thiết cho những vấn đề này. Tuy nhiên, tôi muốn làm nhiều thứ hơn, nhưng mọi thứ đều dựa vào việc khắc phục vấn đề này;) – ccamara

+0

@ccamara Theo '? Broom :: sp_tidy.SpatialPolygonsDataFrame', đối số' region' chỉ định tên của biến từ dữ liệu 'countries @ ' 'được sử dụng để chia nhỏ các vùng. –

2

Trong khi công việc của bạn là một cách tiếp cận hợp lý - Tôi muốn suy nghĩ lại thiết kế của bạn, chủ yếu là vì hai lý do đơn giản:

1) trong khi GeoJSON là tương lai, R vẫn phụ thuộc rất nhiều vào gói sp và các đối tượng sp * phóng viên của nó - rất sớm bạn muốn bạn đã chuyển sang sớm. Nó chỉ là về các gói và hầu hết trong số họ (nếu không phải tất cả) dựa vào các đối tượng sp *.

2) ggplot có khả năng âm mưu lớn kết hợp với ggmap - nhưng nó vẫn còn khá hạn chế so với sp * kết hợp với tờ rơi cho R, vv

lẽ là cách nhanh nhất để đi là đơn giản như:

library(sp) 
library(dplyr) 
library(geojsonio) 
library(dplyr) 
library(tmap) 

#get sp* object instead of geojson 
countries <- geojsonio::geojson_read("foo.geojson",what = "sp") 

#match sp* object with your data.frame 
[email protected] <- dplyr::left_join([email protected], your_df, by = 
c("identifier_1" = "identifier_2")) 

#creates a fast and nice looking plot/lots of configuration available 
p1 <- tm_shape(countries) + 
     tm_polygons() 
p1 

#optional interactive leaflet plot 
tmap_leaflet(p1) 

Nó được viết ra khỏi đầu của tôi/chịu với tôi nếu có vấn đề nhỏ.

Đó là một cách tiếp cận khác nhưng ít nhất là trong mắt tôi một cách tiếp cận nhanh hơn và ngắn gọn hơn trong R ngay bây giờ (hy vọng geojson sẽ nhận được hỗ trợ nhiều hơn trong tương lai).

+0

Cảm ơn câu trả lời của bạn. Tôi hiện đang kiểm tra các tùy chọn và tmap thực sự là một lựa chọn tốt. Trong thực tế, đó là lần đầu tiên của tôi, nhưng tôi đã kết thúc với lỗi này: https://stackoverflow.com/questions/46298066/tmap-error-replacement-has-x-rows-data-has-y (Tôi nghĩ rằng tôi làm cách tiếp cận tương tự như bạn đã làm) và đó là lý do tại sao tôi đã kết thúc thử ggmap (điều đó và thiếu tùy chọn thêm tiêu đề của bản đồ!). Nhân tiện, có điều tôi không hiểu về câu trả lời của bạn: ý của bạn là gì? có một số loại đối tượng R? – ccamara

+1

đọc tài liệu về gói "sp" - từ đầu đến cuối. Nó rất dễ đọc và sẽ cung cấp cho bạn một cái nhìn tổng quan thích hợp làm thế nào để đối phó với dữ liệu không gian. Sau đó tất cả mọi thứ dường như một nửa là khó như nó được sử dụng để được. – Christian

Các vấn đề liên quan