删除给定阈值 epsilon 略有不同的行的最快方法

Fastest method to remove rows that are slightly different by a given threshold epsilon

在我的数据中,我有多个行彼此之间仅略有不同,例如0.001。如果发生这种情况,我只想保留 1 条记录。如果差异小于给定的阈值 epsilon,是否有任何现有的 function/package 可以进行逐行比较并删除行?我在想 distinct(., epsilon = 0.001)

示例:

df <- data.frame(
  IDname = c("aaa1", "bbb2", "ccc3", "ddd4"),
  g = c(0.00501, 0.00499, 2, 2),
  t = c(0.005002, 0.004991, 2.001, 2.0001),
  x = c(1.0001, 1, 2, 2.00001)
)

df

期望的输出:

  IDname       g        t       x
1   aaa1 0.00501 0.005002 1.00010
3   ccc3 2.00000 2.001000 2.00000

为什么没有 round 值 + unique

df <- data.frame(

  g = c(1.001, 1, 2.00001, 2),
  t = c(1, 1.001, 2.001, 2.0001),
  x = c(1.0001, 1, 2, 2.00001)
)

vect <- sapply(df, function(x) unique(round(x, 2)) )
data.frame(vect)

这仅在每列的长度相等时有效。

假设 OP 的示例中存在错误(请参阅我上面的评论),这是在 pasted 行值上使用 duplicated 的解决方案。

如果 OP 澄清并且我误解了问题,将会删除。

# Your data
df <- data.frame(
  IDname = c("aaa1", "bbb2", "ccc3", "ddd4"),
  g = c(0.00501, 0.00499, 2, 2),
  t = c(0.005002, 0.004991, 2.001, 2.0001),
  x = c(1.0001, 1, 2, 2.00001)
)

df[!duplicated(apply(round(df[, -1], 3), 1, paste, collapse = "_")), ];
#  IDname       g        t       x
#1   aaa1 0.00501 0.005002 1.00010
#3   ccc3 2.00000 2.001000 2.00000
#4   ddd4 2.00000 2.000100 2.00001

更一般地适用于任何公差 epsilon:

epsilon <- 0.0001;
df[!duplicated(apply(round(df[, -1], -log10(epsilon) - 1), 1, paste, collapse = "_")), ];

使用层次聚类的方法(灵感来自@BenoitLondon)

我们可以使用欧氏距离矩阵进行层次聚类,并通过相似性完全链接到聚类观察(行)。

# Calculate euclidean distance matrix
dist <- dist(df[, -1], method = "euclidean");

# Perform hierarchical clustering with complete linkage
hc <- hclust(dist, method = "complete");

我们现在可以通过认识到两个 相似 观察值之间的最大欧氏距离由 dmax = sqrt(sum_m epsilon^2) = sqrt(m) * epsilon 给出,其中 m 是数字(数字)列。因此我们可以在h = dmax.

的高度砍树
# Cut the tree
epsilon <- 0.0001;
grp <- cutree(hc, h = sqrt(ncol(df[, -1])) * epsilon);
grp;
#[1] 1 1 2 3    

崩溃的dataframe就是

df[!duplicated(grp), ];
#  IDname       g        t       x
#1   aaa1 0.00501 0.005002 1.00010
#3   ccc3 2.00000 2.001000 2.00000
#4   ddd4 2.00000 2.000100 2.00001