删除给定阈值 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 的示例中存在错误(请参阅我上面的评论),这是在 paste
d 行值上使用 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
在我的数据中,我有多个行彼此之间仅略有不同,例如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 的示例中存在错误(请参阅我上面的评论),这是在 paste
d 行值上使用 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