将不同的 sf 函数应用于数据框中的组
Apply different sf functions to groups in a data frame
我正在尝试使用一组管道 dplyr 函数调用在单个简单要素数据框中计算不同的欧几里德缓冲区(一个 400m 和一个 800m)。应根据分组变量的值为每个要素指定缓冲距离。我可以根据分组变量的已知值轻松拆分数据框,但我想让该方法尽可能通用。
以下代码有效,但显然只有 return所有组的单个 400m 缓冲区:
library(sf)
library(dplyr)
set.seed(42)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
nc$grp <- sample(c(0,1), replace = TRUE, size = 100)
nc_buff <- nc %>%
group_by(grp) %>%
st_transform(32119) %>%
group_map(~ st_buffer(.x, 400))
理想情况下,我会拆分数据帧,计算每个缓冲区,然后 return 将两组缓冲区组合在一起的单个简单特征数据帧。
如何 return 包含 grp == 0 的 400m 缓冲区和 grp == 1 的 800m 缓冲区的单个数据帧?
看起来这样就可以了。 bind_rows()
可通过管道传输,但目前无法在简单要素数据帧上正常工作。
library(sf)
library(dplyr)
set.seed(42)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
nc$grp <- sample(c(0,1), replace = TRUE, size = 100)
nc_buff <- nc %>%
group_by(grp) %>%
st_transform(32119) %>%
group_map(~ st_buffer(.x, case_when(.y$grp == 0 ~ 400, .y$grp == 1 ~ 800)))
# No way to bind_rows() with sf data frames yet so this extra step is needed
# https://github.com/r-spatial/sf/issues/798
nc_buff <- do.call(rbind, nc_buff)
注意:此处给出了更喜欢 do.call(rbind, )
而不是 bind_rows()
的类似推理:.
您实际上不需要 group
数据并使用 group_map
。你
实际上可以将缓冲区宽度向量直接传递给 st_buffer
:
library(sf)
library(dplyr)
set.seed(42)
nc <- st_read(system.file("/shape/nc.shp", package="sf")) %>%
st_transform(32119) %>%
st_centroid() %>%
mutate(grp = sample(c(0,1), 100, replace = TRUE))
在这里,我即时“创建”缓冲区宽度列
nc_buff <- nc %>%
st_buffer(., ifelse(.$grp == 0, 4000, 8000))
plot(nc_buff["NAME"])
对于更复杂的情况或提高可读性,您还可以使用 mutate 预先创建缓冲区列,例如使用 ifelse
或 case_when
:
nc_buff <- nc %>%
mutate(buf_wdt = ifelse(.$grp == 0, 4000, 8000)) %>%
st_buffer(., .$buf_wdt) %>%
select(-buf_wdt)
HTH!
由 reprex package (v0.3.0)
于 2019-12-27 创建
我正在尝试使用一组管道 dplyr 函数调用在单个简单要素数据框中计算不同的欧几里德缓冲区(一个 400m 和一个 800m)。应根据分组变量的值为每个要素指定缓冲距离。我可以根据分组变量的已知值轻松拆分数据框,但我想让该方法尽可能通用。
以下代码有效,但显然只有 return所有组的单个 400m 缓冲区:
library(sf)
library(dplyr)
set.seed(42)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
nc$grp <- sample(c(0,1), replace = TRUE, size = 100)
nc_buff <- nc %>%
group_by(grp) %>%
st_transform(32119) %>%
group_map(~ st_buffer(.x, 400))
理想情况下,我会拆分数据帧,计算每个缓冲区,然后 return 将两组缓冲区组合在一起的单个简单特征数据帧。
如何 return 包含 grp == 0 的 400m 缓冲区和 grp == 1 的 800m 缓冲区的单个数据帧?
看起来这样就可以了。 bind_rows()
可通过管道传输,但目前无法在简单要素数据帧上正常工作。
library(sf)
library(dplyr)
set.seed(42)
nc <- st_read(system.file("shape/nc.shp", package="sf"))
nc$grp <- sample(c(0,1), replace = TRUE, size = 100)
nc_buff <- nc %>%
group_by(grp) %>%
st_transform(32119) %>%
group_map(~ st_buffer(.x, case_when(.y$grp == 0 ~ 400, .y$grp == 1 ~ 800)))
# No way to bind_rows() with sf data frames yet so this extra step is needed
# https://github.com/r-spatial/sf/issues/798
nc_buff <- do.call(rbind, nc_buff)
注意:此处给出了更喜欢 do.call(rbind, )
而不是 bind_rows()
的类似推理:
您实际上不需要 group
数据并使用 group_map
。你
实际上可以将缓冲区宽度向量直接传递给 st_buffer
:
library(sf)
library(dplyr)
set.seed(42)
nc <- st_read(system.file("/shape/nc.shp", package="sf")) %>%
st_transform(32119) %>%
st_centroid() %>%
mutate(grp = sample(c(0,1), 100, replace = TRUE))
在这里,我即时“创建”缓冲区宽度列
nc_buff <- nc %>%
st_buffer(., ifelse(.$grp == 0, 4000, 8000))
plot(nc_buff["NAME"])
对于更复杂的情况或提高可读性,您还可以使用 mutate 预先创建缓冲区列,例如使用 ifelse
或 case_when
:
nc_buff <- nc %>%
mutate(buf_wdt = ifelse(.$grp == 0, 4000, 8000)) %>%
st_buffer(., .$buf_wdt) %>%
select(-buf_wdt)
HTH!
由 reprex package (v0.3.0)
于 2019-12-27 创建