Menggabungkan Shapefile dan dataframe

Sep 17 2020

Saya bekerja Rdengan dataframe biasa ( df) dan shapefile ( map2), kolom yang sama disebut CD116FP. dfmemiliki 103552 baris sedangkan map2memiliki 444. Saya memuat shapefile dengan cara berikut:

peta2 <- read_sf ("D: /Data/tl_2019_us_cd116.shp")

Tujuan akhir saya adalah menggunakan fungsi mapview()untuk melihat peta yang disertakan map2dengan "intensitas" yang dijelaskan di dfbawah kolom np_scores. Karena itu, saya tidak ingin pengamatan dfyang tidak muncul map2.

Inilah pemikiran dan kegagalan saya:

  1. Jika dua objek ini adalah dataframe biasa, kandidat yang masuk akal akan digunakan merge()untuk menggabungkan kedua objek, namun jika Anda menerapkan fungsi itu dalam kasus ini, objek yang dihasilkan kehilangan properti spasial dan mapviewtidak tahu cara membacanya.

  2. Pendekatan lain yang saya gunakan adalah mencoba baris kode ini:

map2m <-data.frame (map2, df [cocok (map2$CD116FP, df$CD116FP),])

Tetapi hasilnya memiliki dimensi yang terlalu besar (jauh lebih besar dari 444 garis) dan karenanya mapviewcrash ketika mencoba memplot peta yang diinginkan.

  1. Akhirnya, saya menggunakan brute force penuh dan hanya membuat loop untuk menambahkan kolom npke map2:
map2$np=10 for (i in c(1:nrow(map2))) { for (j in c(1:nrow(df))) { if (identical(map2$CD116FP[i],df$CD116FP[j])) {map2$np[i]=df$np_score[j]} else {map2$np[i]=0}  
}
}  

Namun, pendekatan ini hanya membutuhkan terlalu banyak waktu mengingat dimensi kerangka data saya.

Apakah Anda punya saran?

Jawaban

3 AllanCameron Sep 19 2020 at 22:24

Saya agak bingung dengan struktur data Anda. Anda dfmemiliki lebih dari 100.000 baris, jadi saya menebak bahwa hal yang sama CD116FPterjadi beberapa kali df, dan npscorekemauannya mungkin berbeda di semua contoh ini. Jika Anda ingin menggabungkannya, map2Anda harus menggabungkannya terlebih dahulu.

Mari kita coba membuat ulang pengaturan serupa:

library(sf)
#> Linking to GEOS 3.8.0, GDAL 3.0.4, PROJ 6.3.1

map2 <- read_sf("C:/users/administrator/documents/shape/tl_2019_us_cd116.shp")

set.seed(69)

df <- data.frame(CD116FP = sprintf("%02d", sample(0:99, 103552, TRUE)),
                 npscores = runif(103552))

head(df)
#>   CD116FP  npscores
#> 1      95 0.6927742
#> 2      80 0.8543845
#> 3      90 0.5220353
#> 4      01 0.1449647
#> 5      76 0.9876543
#> 6      38 0.5629950

Saya telah membuat dfjumlah baris yang sama dengan data Anda untuk menunjukkan solusi ini akan menyesuaikan dengan masalah Anda.

Mari kita gabungkan npscoresdengan dplyr:

library(dplyr)
df_sum <- df %>% 
  filter(CD116FP %in% map2$CD116FP) %>% group_by(CD116FP) %>% summarise(npscores = mean(npscores)) map2$npscores <- df_sum$npscores[match(map2$CD116FP, df_sum$CD116FP)]

Sekarang map2telah agregat yang npscoresdapat kita plot - misalnya, di ggplot:

library(ggplot2)

ggplot(map2) + 
  geom_sf(aes(fill = npscores)) +
  coord_sf(xlim = c(-180, -60),
            ylim = c(15, 70)) +
  scale_fill_gradient(low = "red", high = "gold")

Atau dalam tampilan peta:

library(mapview)
mapView(map2, zcol = "npscores")

Dibuat pada 2020-09-19 oleh paket reprex (v0.3.0)

Alexa Sep 25 2020 at 17:24

Saya beruntung menggunakan paket biasa mergedari paket dasar. Ini kutipan dari karya saya sendiri jika ini berharga bagi Anda :-)

my_data <- read_excel("TraderDataRaw.xlsx", 
      sheet = "fsa", 
      col_types= c("text","text","text","logical","numeric","numeric")) %>% 
      mutate(resp_rate=mailed/responses)

my_map <- st_read("lfsa000b16a_e.shp", stringsAsFactors = FALSE) 

my_merged_data <- merge(my_map, my_data, 
      by.x=c("CFSAUID","PRUID","PRNAME"), 
      by.y=c("CFSAUID","PRUID","PRNAME"))