Unire uno shapefile e un dataframe
Sto lavorando Rcon un normale dataframe ( df) e uno shapefile ( map2), la condivisione di una colonna comune chiamata CD116FP. dfha 103552 linee mentre ha 444. map2Sto caricando lo shapefile nel modo seguente:
map2 <- read_sf ("D: /Data/tl_2019_us_cd116.shp")
Il mio obiettivo finale è utilizzare la funzione mapview()per visualizzare la mappa inclusa map2con l '"intensità" descritta nella dfcolonna np_scores. Pertanto non voglio che le osservazioni di dfciò non compaiano map2.
Ecco i miei pensieri e i miei fallimenti:
Se questi due oggetti fossero frame di dati regolari, un candidato ragionevole sarebbe quello di utilizzare
merge()per combinare entrambi gli oggetti, tuttavia se applichi quella funzione in questo caso, l'oggetto risultante perde le proprietà spaziali emapviewnon sa come leggerlo.Un altro approccio che ho usato è stato provare questa riga di codice:
map2m <-data.frame (map2, df [match (map2$CD116FP, df$CD116FP),])
Ma il risultato ha dimensioni troppo grandi (molto più grandi di 444 linee) e quindi si mapviewblocca quando si tenta di tracciare la mappa desiderata.
- Alla fine, sono andato alla forza bruta completa e ho appena costruito un ciclo per aggiungere la colonna
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}
}
}
Tuttavia, questo approccio richiede troppo tempo date le dimensioni del mio dataframe.
Hai qualche suggerimento?
Risposte
Sono un po 'perplesso dalla struttura dei tuoi dati. Il tuo dfha oltre 100.000 righe, quindi immagino che lo stesso si CD116FPverifichi più volte dfe npscoreche presumibilmente varierà tra queste istanze. Se vuoi unirli a questi map2, dovrai prima aggregarli.
Proviamo a ricreare una configurazione simile:
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
Ho creato dflo stesso numero di righe che i tuoi dati devono mostrare per mostrare che questa soluzione si adatta al tuo problema.
Aggreghiamo il npscorescon 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)]
Ora map2ha l'aggregato npscoresche possiamo tracciare, ad esempio in 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")
O in mapview:
library(mapview)
mapView(map2, zcol = "npscores")
Ho avuto un po 'di fortuna usando il vecchio semplice mergedal pacchetto base. Ecco un estratto dal mio lavoro dovrebbe essere prezioso per te :-)
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"))