提取简单特征数据框中点的坐标
extract coordinates of points in simple feature data frame
我有 2 条线,我需要提取这 2 条线相交的坐标。我正在尝试使用 R 中的 sf 包来做到这一点。
我可以做交叉点,我可以绘制它们,但我无法提取坐标。当每行只有 1 个相交点时它确实有效,但是当有多个(并且在实际数据中有很多)相交点的坐标存储在每行的一个字段中。
inters_pt 看起来像:
class几何
一个 c(3, 3, 3.2, 4.2)
Bc(1.5, 1.5)
C(2, 4)
我收到消息:
Error in st_coordinates.sfc(st_geometry(x)) :
not implemented for objects of class sfc_GEOMETRY
我想提取每个路口的坐标并将属性保留在 'class' 列中。
输出应如下所示:
class几何
一个 (3, 3.2)
一个 (3, 4.2)
乙 (1.5, 1.5)
A (2, 4)
虽然最初我认为它看起来像这样:
class几何
一个 (3, 3)
A (3.2, 4.2)
我错了
搜索让我来到这里:
https://github.com/r-spatial/sf/issues/114
但是那里的解决方案要么掉点 (st_cast(mp, "POINT"),失去属性 'class' 要么抛出以下错误:
Error in vapply(lst, class, rep(NA_character_, 3)) : values must be
length 3, but FUN(X[1]) result is length 2
#First create my data, I create points, and convert them into SpatialLines
lines1.df <- data.frame(
x = c(1,2,3,3,3,3,1,2,3),
y = c(1,2,2,3,4,5,4,4,4),
id = c(rep("A",6), rep("B",3))
)
#with Kyle Walker's functions I convert the points to lines
#https://rpubs.com/walkerke/points_to_line
library(sp)
library(maptools)
points_to_line <- function(data, long, lat, id_field = NULL, sort_field = NULL) {
# Convert to SpatialPointsDataFrame
coordinates(data) <- c(long, lat)
# If there is a sort field...
if (!is.null(sort_field)) {
if (!is.null(id_field)) {
data <- data[order(data[[id_field]], data[[sort_field]]), ]
} else {
data <- data[order(data[[sort_field]]), ]
}
}
# If there is only one path...
if (is.null(id_field)) {
lines <- SpatialLines(list(Lines(list(Line(data)), "id")))
return(lines)
# Now, if we have multiple lines...
} else if (!is.null(id_field)) {
# Split into a list by ID field
paths <- sp::split(data, data[[id_field]])
sp_lines <- SpatialLines(list(Lines(list(Line(paths[[1]])), "line1")))
# I like for loops, what can I say...
for (p in 2:length(paths)) {
id <- paste0("line", as.character(p))
l <- SpatialLines(list(Lines(list(Line(paths[[p]])), id)))
sp_lines <- spRbind(sp_lines, l)
}
return(sp_lines)
}
}
lines1 <- points_to_line(data = lines1.df,
long = "x",
lat = "y",
id_field = "id")
proj4string(lines1) <- CRS("+proj=utm +zone=32 +datum=WGS84")
library(sf)
lines1_sf <- st_as_sf(lines1,
crs = "+proj=utm +zone=32 +datum=WGS84")
lines2.df <- data.frame(
x = c(2,2,2.5,3.5,3.5,2.5,1,2),
y = c(3,4.2,4.2,4.2,3.2,3.2,2,1),
id = c(rep("A",6), rep("B",2))
)
lines2 <- points_to_line(data = lines2.df,
long = "x",
lat = "y",
id_field = "id")
proj4string(lines2) <- CRS("+proj=utm +zone=32 +datum=WGS84")
lines2_sf <- st_as_sf(lines2,
crs = "+proj=utm +zone=32 +datum=WGS84")
#add attributes
lines2_sf$class <- c("A", "B")
#plot both lines
library(ggplot2)
ggplot(lines1_sf) +
geom_sf(aes(color="red")) +
geom_sf(data=lines2_sf) +
coord_sf(crs = "+proj=utm +zone=32 +datum=WGS84") +
theme_bw()
#find intersecting points
#intersect
inters_pt <- st_intersection(lines2_sf, lines1_sf)
#plot shows the intersecting points
ggplot(lines1_sf) +
geom_sf(aes(color="red")) +
geom_sf(data=lines2_sf) +
geom_sf(data=inters_pt) +
coord_sf(crs = "+proj=utm +zone=32 +datum=WGS84") +
theme_bw()
#extract the coordinates from the geometry column
st_coordinates(inters_pt) #<-- gives error
st_cast(inters_pt, "POINT") #removes points
y = as(inters_pt, "Spatial") #loses the 'class' attribute
SpatialPoints(y)
st_cast(st_sfc(inters_pt), "POINT", group_or_split = FALSE) #error
首先,值得使用 sf 从点创建线,这减少了所需的代码量:
library(sf)
library(dplyr)
#First create my data, I create points, and convert them into SpatialLines
lines1.df <- data.frame(
x = c(1,2,3,3,3,3,1,2,3),
y = c(1,2,2,3,4,5,4,4,4),
id = c(rep("A",6), rep("B",3))
)
lines2.df <- data.frame(
x = c(2,2,2.5,3.5,3.5,2.5,1,2),
y = c(3,4.2,4.2,4.2,3.2,3.2,2,1),
id = c(rep("A",6), rep("B",2))
)
points_to_line <- function(data, group = "id"){
data <- data %>%
group_by_at(group) %>%
summarise(do_union = FALSE) %>%
st_cast("LINESTRING") %>%
ungroup %>%
select(-do_union)
}
crs <- "+proj=utm +zone=32 +datum=WGS84"
coords <- c("x", "y")
lines1_sf <- st_as_sf(lines1.df, coords = coords, crs = crs) %>%
points_to_line()
lines2_sf <- st_as_sf(lines2.df, coords = coords, crs = crs) %>%
points_to_line()
#add attributes
lines2_sf$class <- c("A", "B")
#find intersecting points
#intersect
inters_pt <- st_intersection(lines1_sf, lines2_sf)
这里需要先转MULTIPOINT再转POINT
#extract the coordinates from the geometry column
inters_pt <- inters_pt %>%
st_cast("MULTIPOINT") %>%
st_cast("POINT")
> st_coordinates(inters_pt)
# X Y
#1 3.0 3.2
#2 3.0 4.2
#3 2.0 4.0
#4 1.5 1.5
我有 2 条线,我需要提取这 2 条线相交的坐标。我正在尝试使用 R 中的 sf 包来做到这一点。 我可以做交叉点,我可以绘制它们,但我无法提取坐标。当每行只有 1 个相交点时它确实有效,但是当有多个(并且在实际数据中有很多)相交点的坐标存储在每行的一个字段中。
inters_pt 看起来像: class几何 一个 c(3, 3, 3.2, 4.2) Bc(1.5, 1.5) C(2, 4)
我收到消息:
Error in st_coordinates.sfc(st_geometry(x)) : not implemented for objects of class sfc_GEOMETRY
我想提取每个路口的坐标并将属性保留在 'class' 列中。
输出应如下所示: class几何 一个 (3, 3.2) 一个 (3, 4.2) 乙 (1.5, 1.5) A (2, 4)
虽然最初我认为它看起来像这样: class几何 一个 (3, 3) A (3.2, 4.2)
我错了
搜索让我来到这里: https://github.com/r-spatial/sf/issues/114
但是那里的解决方案要么掉点 (st_cast(mp, "POINT"),失去属性 'class' 要么抛出以下错误:
Error in vapply(lst, class, rep(NA_character_, 3)) : values must be length 3, but FUN(X[1]) result is length 2
#First create my data, I create points, and convert them into SpatialLines
lines1.df <- data.frame(
x = c(1,2,3,3,3,3,1,2,3),
y = c(1,2,2,3,4,5,4,4,4),
id = c(rep("A",6), rep("B",3))
)
#with Kyle Walker's functions I convert the points to lines
#https://rpubs.com/walkerke/points_to_line
library(sp)
library(maptools)
points_to_line <- function(data, long, lat, id_field = NULL, sort_field = NULL) {
# Convert to SpatialPointsDataFrame
coordinates(data) <- c(long, lat)
# If there is a sort field...
if (!is.null(sort_field)) {
if (!is.null(id_field)) {
data <- data[order(data[[id_field]], data[[sort_field]]), ]
} else {
data <- data[order(data[[sort_field]]), ]
}
}
# If there is only one path...
if (is.null(id_field)) {
lines <- SpatialLines(list(Lines(list(Line(data)), "id")))
return(lines)
# Now, if we have multiple lines...
} else if (!is.null(id_field)) {
# Split into a list by ID field
paths <- sp::split(data, data[[id_field]])
sp_lines <- SpatialLines(list(Lines(list(Line(paths[[1]])), "line1")))
# I like for loops, what can I say...
for (p in 2:length(paths)) {
id <- paste0("line", as.character(p))
l <- SpatialLines(list(Lines(list(Line(paths[[p]])), id)))
sp_lines <- spRbind(sp_lines, l)
}
return(sp_lines)
}
}
lines1 <- points_to_line(data = lines1.df,
long = "x",
lat = "y",
id_field = "id")
proj4string(lines1) <- CRS("+proj=utm +zone=32 +datum=WGS84")
library(sf)
lines1_sf <- st_as_sf(lines1,
crs = "+proj=utm +zone=32 +datum=WGS84")
lines2.df <- data.frame(
x = c(2,2,2.5,3.5,3.5,2.5,1,2),
y = c(3,4.2,4.2,4.2,3.2,3.2,2,1),
id = c(rep("A",6), rep("B",2))
)
lines2 <- points_to_line(data = lines2.df,
long = "x",
lat = "y",
id_field = "id")
proj4string(lines2) <- CRS("+proj=utm +zone=32 +datum=WGS84")
lines2_sf <- st_as_sf(lines2,
crs = "+proj=utm +zone=32 +datum=WGS84")
#add attributes
lines2_sf$class <- c("A", "B")
#plot both lines
library(ggplot2)
ggplot(lines1_sf) +
geom_sf(aes(color="red")) +
geom_sf(data=lines2_sf) +
coord_sf(crs = "+proj=utm +zone=32 +datum=WGS84") +
theme_bw()
#find intersecting points
#intersect
inters_pt <- st_intersection(lines2_sf, lines1_sf)
#plot shows the intersecting points
ggplot(lines1_sf) +
geom_sf(aes(color="red")) +
geom_sf(data=lines2_sf) +
geom_sf(data=inters_pt) +
coord_sf(crs = "+proj=utm +zone=32 +datum=WGS84") +
theme_bw()
#extract the coordinates from the geometry column
st_coordinates(inters_pt) #<-- gives error
st_cast(inters_pt, "POINT") #removes points
y = as(inters_pt, "Spatial") #loses the 'class' attribute
SpatialPoints(y)
st_cast(st_sfc(inters_pt), "POINT", group_or_split = FALSE) #error
首先,值得使用 sf 从点创建线,这减少了所需的代码量:
library(sf)
library(dplyr)
#First create my data, I create points, and convert them into SpatialLines
lines1.df <- data.frame(
x = c(1,2,3,3,3,3,1,2,3),
y = c(1,2,2,3,4,5,4,4,4),
id = c(rep("A",6), rep("B",3))
)
lines2.df <- data.frame(
x = c(2,2,2.5,3.5,3.5,2.5,1,2),
y = c(3,4.2,4.2,4.2,3.2,3.2,2,1),
id = c(rep("A",6), rep("B",2))
)
points_to_line <- function(data, group = "id"){
data <- data %>%
group_by_at(group) %>%
summarise(do_union = FALSE) %>%
st_cast("LINESTRING") %>%
ungroup %>%
select(-do_union)
}
crs <- "+proj=utm +zone=32 +datum=WGS84"
coords <- c("x", "y")
lines1_sf <- st_as_sf(lines1.df, coords = coords, crs = crs) %>%
points_to_line()
lines2_sf <- st_as_sf(lines2.df, coords = coords, crs = crs) %>%
points_to_line()
#add attributes
lines2_sf$class <- c("A", "B")
#find intersecting points
#intersect
inters_pt <- st_intersection(lines1_sf, lines2_sf)
这里需要先转MULTIPOINT再转POINT
#extract the coordinates from the geometry column
inters_pt <- inters_pt %>%
st_cast("MULTIPOINT") %>%
st_cast("POINT")
> st_coordinates(inters_pt)
# X Y
#1 3.0 3.2
#2 3.0 4.2
#3 2.0 4.0
#4 1.5 1.5