合并 Shapefile 和数据框

Merging a Shapefile and a dataframe

我在 R 中使用常规数据框 (df) 和 shapefile (map2) 工作,共享一个名为 CD116FP 的公共列。 df 有 103552 行,而 map2 有 444 行。我按以下方式加载 shapefile:

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

我的最终目标是使用函数 mapview() 查看 map2 中包含的地图,其“强度”在 df 列下的 [=20] 中描述=].因此,我不希望 df 的观察结果没有出现在 map2.

以下是我的想法和失败:

  1. 如果这两个对象是常规数据帧,一个合理的候选者是使用 merge() 来组合两个对象,但是如果您在这种情况下应用该函数,生成的对象将失去空间属性和 mapview 不知道如何阅读它。

  2. 我使用的另一种方法是尝试这行代码:

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

但结果的维度太大(比 444 行大得多),因此 mapview 在尝试绘制所需地图时崩溃。

  1. 最后,我全力以赴,只是构建了一个循环,将列 np 添加到 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}  
}
}  

但是,考虑到我的数据框的尺寸,这种方法会花费太多时间。

你有什么建议吗?

我对你的数据结构有点不解。您的 df 有超过 100,000 行,所以我猜测相同的 CD116FPdf 中出现了多次,并且 npscore 可能会因这些实例而异。如果您想将它们合并到 map2,您需要先将它们聚合。

让我们尝试重新创建一个类似的设置:

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

我已使 df 的行数与您的数据必须显示的行数相同,以显示此解决方案将扩展到您的问题。

让我们将 npscoresdplyr 相加:

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)]

现在 map2 有我们可以绘制的聚合 npscores - 例如,在 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")

或在地图视图中:

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

reprex package (v0.3.0)

于 2020-09-19 创建

我使用基本包中的普通旧 merge 运气不错。如果这对您有价值的话,这是我自己工作的摘录:-)

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"))