R:识别由两列中的共享值连接的数据框行
R: Identifying Data Frame Rows Connected By Shared Values In Two Columns
我的 objective 是根据 R 中两列之间的共享值识别单个数据框中的 "connected" 行。
在此示例中,有 10 个唯一段(即数据集群),它们由与每个唯一段对应的整数标识。每行代表两个段,这两个段已被确定为彼此在某个距离阈值内。 "segA" 和 "segB" 列之间没有显着区别,它们只是用于跟踪连接的线段对。 "dist" 列表示线段对之间的距离,但此时并不真正需要,因为数据框仅包含那些被视为 "connected."
的线段对
我正在尝试找出一种方法来识别在 "segA" 或 "segB" 中至少具有一个共享值的所有行,指示行之间的连接段。
我最初的尝试是对循环和逻辑语句进行了复杂的尝试(我是 R 编程的新手),所以我将不胜感激任何简洁的解决方案!
示例:
df = data.frame(
segA = c(1, 1, 2, 4, 6, 7, 9),
segB = c(2, 3, 4, 5, 8, 8, 10),
dist = c(0.5321, 0.3212, 0.4351, 0.1421, 0.5125, 0.1692, 0.3218)
)
df
segA segB dist
1 1 2 0.5321
2 1 3 0.3212
3 2 4 0.4351
4 4 5 0.1421
5 6 8 0.5125
6 7 8 0.1692
7 9 10 0.3218
第 1 行和第 2 行相连,因为它们都包含段“1”。
第 3 行和第 1 行相连,因为它们都包含段“2”等。
尽管第 2 行和第 3 行没有通过共享段的存在直接连接,但总体而言,它们通过第 1 行的相互连接而连接。
所需的最终输出类似于:
(1) = 1, 2, 3, 4, 5
(2) = 6, 7, 8
(3) = 9, 10
其中 (1)、(2) 和 (3) 代表不同的整体段及其 directly/mutually 连接的组件。
## helper function for merging vector elements of a list
merge.elems <- function(x,i,j) {
c(
x[seq_len(i-1L)], ## before i
list(unique(c(x[[i]],x[[j]]))), ## combined i,j
x[seq_len(j-i-1L)+i], ## between i,j
x[seq_len(length(x)-j)+j] ## after j
);
}; ## end merge.elems()
## initialize row groups and value groups
rgs <- as.list(seq_len(nrow(df)));
vgs <- do.call(Map,c(c,unname(df[1:2])));
## if there are 2 or more groups, exhaustively merge overlapping value group pairs
if (length(rgs)>1L) {
i <- 1L;
j <- 2L;
repeat {
if (any(vgs[[i]]%in%vgs[[j]])) {
rgs <- merge.elems(rgs,i,j);
vgs <- merge.elems(vgs,i,j);
j <- i+1L;
if (j>length(rgs)) break;
} else {
j <- j+1L;
if (j>length(rgs)) {
i <- i+1L;
if (i==length(rgs)) break;
j <- i+1L;
}; ## end if
}; ## end if
}; ## end repeat
}; ## end if
## results
rgs;
## [[1]]
## [1] 1 2 3 4
##
## [[2]]
## [1] 5 6
##
## [[3]]
## [1] 7
##
vgs;
## [[1]]
## [1] 1 2 3 4 5
##
## [[2]]
## [1] 6 8 7
##
## [[3]]
## [1] 9 10
##
我的 objective 是根据 R 中两列之间的共享值识别单个数据框中的 "connected" 行。
在此示例中,有 10 个唯一段(即数据集群),它们由与每个唯一段对应的整数标识。每行代表两个段,这两个段已被确定为彼此在某个距离阈值内。 "segA" 和 "segB" 列之间没有显着区别,它们只是用于跟踪连接的线段对。 "dist" 列表示线段对之间的距离,但此时并不真正需要,因为数据框仅包含那些被视为 "connected."
的线段对我正在尝试找出一种方法来识别在 "segA" 或 "segB" 中至少具有一个共享值的所有行,指示行之间的连接段。
我最初的尝试是对循环和逻辑语句进行了复杂的尝试(我是 R 编程的新手),所以我将不胜感激任何简洁的解决方案!
示例:
df = data.frame(
segA = c(1, 1, 2, 4, 6, 7, 9),
segB = c(2, 3, 4, 5, 8, 8, 10),
dist = c(0.5321, 0.3212, 0.4351, 0.1421, 0.5125, 0.1692, 0.3218)
)
df
segA segB dist
1 1 2 0.5321
2 1 3 0.3212
3 2 4 0.4351
4 4 5 0.1421
5 6 8 0.5125
6 7 8 0.1692
7 9 10 0.3218
第 1 行和第 2 行相连,因为它们都包含段“1”。
第 3 行和第 1 行相连,因为它们都包含段“2”等。
尽管第 2 行和第 3 行没有通过共享段的存在直接连接,但总体而言,它们通过第 1 行的相互连接而连接。
所需的最终输出类似于:
(1) = 1, 2, 3, 4, 5
(2) = 6, 7, 8
(3) = 9, 10
其中 (1)、(2) 和 (3) 代表不同的整体段及其 directly/mutually 连接的组件。
## helper function for merging vector elements of a list
merge.elems <- function(x,i,j) {
c(
x[seq_len(i-1L)], ## before i
list(unique(c(x[[i]],x[[j]]))), ## combined i,j
x[seq_len(j-i-1L)+i], ## between i,j
x[seq_len(length(x)-j)+j] ## after j
);
}; ## end merge.elems()
## initialize row groups and value groups
rgs <- as.list(seq_len(nrow(df)));
vgs <- do.call(Map,c(c,unname(df[1:2])));
## if there are 2 or more groups, exhaustively merge overlapping value group pairs
if (length(rgs)>1L) {
i <- 1L;
j <- 2L;
repeat {
if (any(vgs[[i]]%in%vgs[[j]])) {
rgs <- merge.elems(rgs,i,j);
vgs <- merge.elems(vgs,i,j);
j <- i+1L;
if (j>length(rgs)) break;
} else {
j <- j+1L;
if (j>length(rgs)) {
i <- i+1L;
if (i==length(rgs)) break;
j <- i+1L;
}; ## end if
}; ## end if
}; ## end repeat
}; ## end if
## results
rgs;
## [[1]]
## [1] 1 2 3 4
##
## [[2]]
## [1] 5 6
##
## [[3]]
## [1] 7
##
vgs;
## [[1]]
## [1] 1 2 3 4 5
##
## [[2]]
## [1] 6 8 7
##
## [[3]]
## [1] 9 10
##