查找具有范围的值的重复项,并用R求和
我确实有一个ID为value1、value2和value3的df,看起来如下所示:查找具有范围的值的重复项,并用R求和,r,duplicates,range,R,Duplicates,Range,我确实有一个ID为value1、value2和value3的df,看起来如下所示: ID val1 val2 val3 01 100.5 7.31 1000 02 100.0 7.33 100 03 100.1 10.40 500 04 105.3 7.28 100 05 100.4 7.30 500 val1和val2有范围,让我们假设以下范围:val1=0.5和val=0.1 ID val1
ID val1 val2 val3
01 100.5 7.31 1000
02 100.0 7.33 100
03 100.1 10.40 500
04 105.3 7.28 100
05 100.4 7.30 500
val1和val2有范围,让我们假设以下范围:val1=0.5和val=0.1
ID val1 val2 val3
01 100.5±0.5 7.31±0.1 1000
02 100.0±0.5 7.33±0.1 100
03 100.1±0.5 10.40±0.1 500
04 105.3±0.5 7.28±0.1 100
05 100.4 ±0.5 7.30±0.1 500
我想总结一下在val1和val2范围内重叠的行。只有当这两个条件为真时,才应发生val3之和。最后,该表应仅包含ID较低的行和汇总值3。在我的示例中,这仅适用于第一行、第二行和最后一行。此外,所有不符合这两个标准的行都应该保留。这就是我想要的结果:
ID val1 val2 val3
01 100.5 7.31 1600
03 100.1 10.40 500
04 105.3 7.28 100
到目前为止,我试图通过distinct
函数实现这一点。然而,这并没有考虑我的范围和总结
sum_up <- distinct(df, val1, val2, .keep_all = TRUE)
sum\u upEDIT:我对此做了更多的思考,并提出了一个更优雅的解决方案,可以处理任意长的数据帧。该解决方案假定数据已根据ID排序
n <- nrow(data)
used <- logical(n)
groups <- numeric(n)
i <- 1
for (j in 1:n) {
if (used[j]) next
indices1 <- abs(val1[j] - val1) <= range1
indices2 <- abs(val2[j] - val2) <= range2
indices <- which(indices1 & indices2 & !used)
groups[indices] <- i
used[indices] <- TRUE
i <- i + 1
}
现在可以使用附加列进行分组。不过,我希望您的数据帧没有太多行。这将导致解决方案效率低下。请注意,您要求这两个条件都为真,而这仅发生在ID 01中。然而,对于您的预期输出,如果第一个条件(val1)为真,您看起来就没事了。您能否更新您的问题以澄清?99.8(第3行)是否与第100行(第2行)重叠?还是每行只重叠一次?@JakobGepp:你说得对,第(2)行的99.8与100.0重叠,但第2行的值不重叠。我只想总结一下满足这两个条件的行。@BenNorris:我试图澄清我的问题,因此我添加了同时满足这两个条件的行(5)。只有符合这两个条件的行才应合并,所有其他行都应保留。作为引用的是ID最低的行还是最近的行?假设A行与B行重叠,B行与D行重叠,但A行与D行不重叠。您是否将这三行相加,因为B行是公共链接?还是D行开始了一个新的分组?谢谢你的解决方案,我适应了我的代码。我最终得到了一个结果表,但是您已经担心我当前使用的数据集有几行(~3000)。这会导致渲染时间过长。。。Markus描述的链接(总是ID最低的链接)正是我的目标。我已经用一个不同的解决方案更新了答案,这个解决方案要短得多,可能更具表现力,并且应该可以处理较长的数据帧。
data <- data.frame(
ID = 1:5,
val1 = c(100.5, 100, 100.1, 105.3, 100.4),
val2 = c(7.31, 7.33, 10.4, 7.28, 7.3),
val3 = c(1000, 100, 500, 100, 500),
groups = rep(0, 5)
)
range1 <- .5
range2 <- .1
overlap1 <- abs(outer(data[, "val1"], data[, "val1"], "-")) <= range1
overlap2 <- abs(outer(data[, "val2"], data[, "val2"], "-")) <= range2
overlap_both <- overlap1 & overlap2
result <- list()
ignore <- numeric(ncol(overlap_both))
for (i in 1:ncol(overlap_both)) {
for(j in i:ncol(overlap_both)) {
# Ignore this index if the element was already combined with a previous
# element. Otherwise a row in the dataframe would fall in two different
# groups.
if (j %in% ignore) {
next
}
if (any(overlap_both[, i] & overlap_both[, j])) {
result[[length(result) + 1]] <- overlap_both[, i] | overlap_both[, j]
ignore[[j]] <- j
}
}
}
result <- unique(result)
for (i in seq_along(result)) {
data[which(result[[i]]), "groups"] <- i
}