首页 > 解决方案 > 在坐标对的数据框中获取坐标对的行数

问题描述

假设我有一个名为“边缘”的点对数据框,比如:

  x0       y0       x1       y1
1 2.464286 2.464286 2.583333 1.750000
2 0.700000 3.787500 2.464286 2.464286
3 2.464286 2.464286 3.500000 3.500000
4 3.500000 3.500000 4.300000 3.900000
5 2.250000 4.750000 3.500000 3.500000

数据帧的每一行都是从点 (x0,y0) 到点 (x1,y1) 的边,例如我的第一条边从坐标点 (2.464286,2.464286) 到点 (2.583333,1.750000)

从该数据帧中,我可以轻松地提取另一个数据帧,称之为“顶点”,其中每个点只出现一次:

  x        y
1 2.464286 2.464286
2 0.700000 3.787500
3 3.500000 3.500000
4 2.250000 4.750000
5 2.583333 1.750000
6 4.300000 3.900000

如何用它出现在数据框“边缘”中的行号标记“顶点”中的每个点,不管是左端点还是右端点?也就是说,我想得到这样的东西:

  x        y            occurrences
1 2.464286 2.464286     1,2,3
2 0.700000 3.787500     2
3 3.500000 3.500000     3,4,5
4 2.250000 4.750000     5
5 2.583333 1.750000     1
6 4.300000 3.900000     4

我尝试使用 %in% 和 which,但它只考虑元素比较,因此具有相同 x 坐标或 y 坐标的两个点可以被视为相同。

此外,这是一个标签化,我必须在我的模拟中做很多次,所以我希望得到一个比基于 for-loop/if 的解决方案更好的解决方案。

标签: rdataframe

解决方案


这是一个使用dplyr. 可能有一种方法可以清理它,但这应该可以让你大部分时间到达那里。

library(dplyr)

edgedf <- read.table(header = TRUE,stringsAsFactors = FALSE, text = "
x0       y0       x1       y1
2.464286 2.464286 2.583333 1.750000
0.700000 3.787500 2.464286 2.464286
2.464286 2.464286 3.500000 3.500000
3.500000 3.500000 4.300000 3.900000
2.250000 4.750000 3.500000 3.500000")


vertdf <- read.table(header = TRUE,stringsAsFactors = FALSE, text = "
x        y
2.464286 2.464286
0.700000 3.787500
3.500000 3.500000
2.250000 4.750000
2.583333 1.750000
4.300000 3.900000")

# Add row numbers
tmp_edgedf <- edgedf %>% mutate(id = 1:n())
# Stack the x0,y0 and x1,y1 coords as x,y then join
# with vertices "vertdf". Grouping by x,y and summarise
# concatenating the row numbers as occurrences.
rbind(tmp_edgedf %>%
        select(id, x0, y0) %>%
        rename(x = x0, y = y0),
      tmp_edgedf %>%
        select(id, x1, y1) %>%
        rename(x = x1, y = y1)) %>%
  right_join(vertdf, by = c("x", "y")) %>%
  group_by(x, y) %>%
  summarise(occurrences = paste(sort(id), collapse = ",")) %>%
  data.frame() # Remove rounding by tibble object.

结果

##          x        y occurrences
## 1 0.700000 3.787500           2
## 2 2.250000 4.750000           5
## 3 2.464286 2.464286       1,2,3
## 4 2.583333 1.750000           1
## 5 3.500000 3.500000       3,4,5
## 6 4.300000 3.900000           4

编辑

下面是一个变体,也许更简单的解决方案。第一个inner_join将顶点连接到(x0, y0),第二个连接到(x1, y1)。将行号添加到edgedf数据结构(临时)以跟踪行号。数据框可以在edgedf连接之前添加,消除重复添加。

rbind(
    inner_join(vertdf, 
               edgedf %>% transmute(id = 1:n(), x0, y0),
               by = c(x = "x0", y = "y0")),
    inner_join(vertdf,
               edgedf %>% transmute(id = 1:n(), x1, y1),
               by = c(x = "x1", y = "y1"))
  ) %>%
  group_by(x,y) %>%
  summarise(occurrances = paste(sort(id), collapse = ",")) %>%
  data.frame()

推荐阅读