Mesclando um Shapefile e um dataframe
Estou trabalhando Rcom um dataframe regular ( df) e um shapefile ( map2), o compartilhamento de uma coluna comum chamada CD116FP. dftem 103552 linhas enquanto map2tem 444. Estou carregando o shapefile da seguinte maneira:
map2 <- read_sf ("D: /Data/tl_2019_us_cd116.shp")
Meu objetivo final é usar a função mapview()para visualizar o mapa incluído map2com a "intensidade" descrita na dfcoluna np_scores. Portanto, não quero observações de dfque não apareçam map2.
Aqui estão meus pensamentos e falhas:
Se esses dois objetos fossem dataframes regulares, um candidato razoável seria usar
merge()para combinar os dois objetos; no entanto, se você aplicar essa função neste caso, o objeto resultante perde as propriedades espaciais emapviewnão sabe como lê-lo.Outra abordagem que usei foi tentar esta linha de código:
map2m <-data.frame (map2, df [match (map2$CD116FP, df$CD116FP),])
Mas o resultado tem dimensões muito grandes (muito maiores que 444 linhas) e, portanto, mapviewfalha ao tentar plotar o mapa desejado.
- Por fim, usei força bruta total e acabei de construir um loop para adicionar a coluna
npamap2:
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}
}
}
No entanto, essa abordagem leva muito tempo, dadas as dimensões do meu dataframe.
Você tem alguma sugestão?
Respostas
Estou um pouco intrigado com a estrutura dos seus dados. Seu dftem mais de 100.000 linhas, então estou supondo que o mesmo CD116FPocorre várias vezes em df, e npscoreprovavelmente irá variar entre essas instâncias. Se você quiser mesclá- map2los, precisará agregá-los primeiro.
Vamos tentar recriar uma configuração semelhante:
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
Eu criei dfo mesmo número de linhas que seus dados têm para mostrar que essa solução será dimensionada para seu problema.
Vamos agregar npscorescom 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)]
Agora map2tem o agregado npscoresque podemos plotar - por exemplo, no 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")
Ou no mapview:
library(mapview)
mapView(map2, zcol = "npscores")
Tive sorte com o uso mergedo pacote básico. Aqui está um trecho do meu próprio trabalho, se isso for valioso para você :-)
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"))