假设我们的输入数据框是内置的 11x8 anscombe 数据框。它的前三列名称是x1、x2 和x3。那么这里有一些解决方案。
1) sqldf 这会返回相似行的行号对:
library(sqldf)
ans <- anscombe
ans$id <- 1:nrow(ans)
sqldf("select a.id, b.id
from ans a
join ans b on abs(a.x1 - b.x1) <= 1 and
abs(a.x2 - b.x2) <= 1 and
abs(a.x3 - b.x3) <= 1")
添加另一个条件and a.id < b.id,如果每行不应该与自身配对并且如果我们想要排除每对的反向或添加and not a.id = b.id 以仅排除自身对。
2) dist 这将返回一个矩阵m,如果 i 和 j 行相似,则其第 i,j 个元素为 1,如果不基于第 1、2 和 3 列,则返回 0。
# matrix of pairs (1 = similar, 0 = not)
m <- (as.matrix(dist(anscombe[1:3], method = "maximum")) <= 1) + 0
给予:
1 2 3 4 5 6 7 8 9 10 11
1 1 0 0 1 1 0 0 0 0 0 0
2 0 1 0 1 0 0 0 0 0 1 0
3 0 0 1 0 0 1 0 0 1 0 0
4 1 1 0 1 0 0 0 0 0 0 0
5 1 0 0 0 1 0 0 0 1 0 0
6 0 0 1 0 0 1 0 0 0 0 0
7 0 0 0 0 0 0 1 0 0 1 1
8 0 0 0 0 0 0 0 1 0 0 1
9 0 0 1 0 1 0 0 0 1 0 0
10 0 1 0 0 0 0 1 0 0 1 0
11 0 0 0 0 0 0 1 1 0 0 1
如果需要,我们可以添加 m[lower.tri(m, diag = TRUE)] <- 0 来排除自我配对和每对的反面,或者添加 diag(m) <- 0 来排除自我配对。
我们可以像这样创建相似行号对的数据框。为了保持输出简短,我们排除了自我对和每对的反向。
# two-column data.frame of pairs excluding self pairs and reverses
subset(as.data.frame.table(m), c(Var1) < c(Var2) & Freq == 1)[1:2]
给予:
Var1 Var2
34 1 4
35 2 4
45 1 5
58 3 6
91 3 9
93 5 9
101 2 10
106 7 10
117 7 11
118 8 11
这是上面的网络图。请注意,答案在图表之后继续:
# network graph
library(igraph)
g <- graph.adjacency(m)
plot(g)
# raster plot
library(ggplot2)
ggplot(as.data.frame.table(m), aes(Var1, Var2, fill = factor(Freq))) +
geom_raster()