合并 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
.
上
以下是我的想法和失败:
如果这两个对象是常规数据帧,一个合理的候选者是使用 merge()
来组合两个对象,但是如果您在这种情况下应用该函数,生成的对象将失去空间属性和 mapview
不知道如何阅读它。
我使用的另一种方法是尝试这行代码:
map2m<-data.frame(map2, df[match(map2$CD116FP, df$CD116FP),])
但结果的维度太大(比 444 行大得多),因此 mapview
在尝试绘制所需地图时崩溃。
- 最后,我全力以赴,只是构建了一个循环,将列
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 行,所以我猜测相同的 CD116FP
在 df
中出现了多次,并且 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
的行数与您的数据必须显示的行数相同,以显示此解决方案将扩展到您的问题。
让我们将 npscores
与 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)]
现在 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"))
我在 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
.
以下是我的想法和失败:
如果这两个对象是常规数据帧,一个合理的候选者是使用
merge()
来组合两个对象,但是如果您在这种情况下应用该函数,生成的对象将失去空间属性和mapview
不知道如何阅读它。我使用的另一种方法是尝试这行代码:
map2m<-data.frame(map2, df[match(map2$CD116FP, df$CD116FP),])
但结果的维度太大(比 444 行大得多),因此 mapview
在尝试绘制所需地图时崩溃。
- 最后,我全力以赴,只是构建了一个循环,将列
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 行,所以我猜测相同的 CD116FP
在 df
中出现了多次,并且 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
的行数与您的数据必须显示的行数相同,以显示此解决方案将扩展到您的问题。
让我们将 npscores
与 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)]
现在 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")
我使用基本包中的普通旧 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"))