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

时间:2017-11-11 22:22:45

标签: r duplicates unique diff distinct

在我的数据中,我有多行只是彼此略有不同,例如0.001。如果发生这种情况,我想只保留1条记录。是否存在可以进行逐行比较的现有函数/包,如果差异小于给定的阈值epsilon,则删除行?我在想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

2 个答案:

答案 0 :(得分:2)

为什么没有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)

仅当每列的长度相等时才有效。

答案 1 :(得分:1)

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

如果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