计算 R data.table 中的值向量
Calculation on a vector of values in a R data.table
我在 R 中有以下 data.table:
dataset <- data.table(C=c("a", "b", "c") , neg=c("5, 7", "9", "3, 4, 5"), pos = c("5.05, 8", "", "2.95, 4.2"))
table 看起来像这样:
我想找到“neg”和“pos”列中值之间的重叠。
如果同一行中两列中的任何值之间的差异小于 0.1 - 我想通过取两个值的平均值来合并这些值。
例如。对于 5 和 5.05 这对 – 应该计算 5.025。如果在相同的 0.1 范围内没有值,则只显示原始值。我添加了一张我对可能结果的想法的图片:
是否有直接执行此操作的功能,或者我必须拆分/重新排列之前的 table?
感谢您的帮助!
数字存储为字符值,因此首先您需要用逗号分隔它们,将它们转换为数字,sort
数据。然后,您可以计算连续值之间的差异,如果它们的差异小于 0.1,则将这两个值合并(通过取平均值)。
在基础 R 中,使用 Map
和 tapply
你可以做 -
dataset$overlap <- Map(function(x, y) {
p <- sort(as.numeric(c(x, y)))
as.numeric(tapply(p, cumsum(c(TRUE, diff(p) > 0.1)), mean))
}, strsplit(dataset$neg, ',\s*'), strsplit(dataset$pos, ',\s*'))
dataset
# C neg pos overlap
#1: a 5, 7 5.05, 8 5.025,7.000,8.000
#2: b 9 9
#3: c 3, 4, 5 2.95, 4.2 2.975,4.000,4.200,5.000
dataset$overlap
#[[1]]
#[1] 5.025 7.000 8.000
#[[2]]
#[1] 9
#[[3]]
#[1] 2.975 4.000 4.200 5.000
在问题的示例中,任何输入单元格中没有彼此相差 0.1 以内的值,我们假设这是一般情况,否则也可以合并这些值。
对于每一行,将数字扫描到一个数值向量中,对其进行排序并找到相邻数字小于 0.1 的实例。将这些数字的平均值和 NA 取出先前的数字。省略 NA 并转换为逗号分隔的字符串。
如果 C 中的值是唯一的,那么我们可以将 by= 替换为 by=C。
dataset[, overlap := {
s <- sort(scan(text = c(neg, pos), sep = ",", quiet = TRUE))
wx <- which(c(FALSE, diff(s) < 0.1))
s[wx] <- (s[wx] + s[wx-1]) / 2
s[wx-1] <- NA
toString(na.omit(s))
}, by = 1:nrow(dataset)]
dataset
## C neg pos overlap
## 1: a 5, 7 5.05, 8 5.025, 7, 8
## 2: b 9 9
## 3: c 3, 4, 5 2.95, 4.2 2.975, 4, 4.2, 5
我在 R 中有以下 data.table:
dataset <- data.table(C=c("a", "b", "c") , neg=c("5, 7", "9", "3, 4, 5"), pos = c("5.05, 8", "", "2.95, 4.2"))
table 看起来像这样:
我想找到“neg”和“pos”列中值之间的重叠。 如果同一行中两列中的任何值之间的差异小于 0.1 - 我想通过取两个值的平均值来合并这些值。 例如。对于 5 和 5.05 这对 – 应该计算 5.025。如果在相同的 0.1 范围内没有值,则只显示原始值。我添加了一张我对可能结果的想法的图片:
是否有直接执行此操作的功能,或者我必须拆分/重新排列之前的 table?
感谢您的帮助!
数字存储为字符值,因此首先您需要用逗号分隔它们,将它们转换为数字,sort
数据。然后,您可以计算连续值之间的差异,如果它们的差异小于 0.1,则将这两个值合并(通过取平均值)。
在基础 R 中,使用 Map
和 tapply
你可以做 -
dataset$overlap <- Map(function(x, y) {
p <- sort(as.numeric(c(x, y)))
as.numeric(tapply(p, cumsum(c(TRUE, diff(p) > 0.1)), mean))
}, strsplit(dataset$neg, ',\s*'), strsplit(dataset$pos, ',\s*'))
dataset
# C neg pos overlap
#1: a 5, 7 5.05, 8 5.025,7.000,8.000
#2: b 9 9
#3: c 3, 4, 5 2.95, 4.2 2.975,4.000,4.200,5.000
dataset$overlap
#[[1]]
#[1] 5.025 7.000 8.000
#[[2]]
#[1] 9
#[[3]]
#[1] 2.975 4.000 4.200 5.000
在问题的示例中,任何输入单元格中没有彼此相差 0.1 以内的值,我们假设这是一般情况,否则也可以合并这些值。
对于每一行,将数字扫描到一个数值向量中,对其进行排序并找到相邻数字小于 0.1 的实例。将这些数字的平均值和 NA 取出先前的数字。省略 NA 并转换为逗号分隔的字符串。
如果 C 中的值是唯一的,那么我们可以将 by= 替换为 by=C。
dataset[, overlap := {
s <- sort(scan(text = c(neg, pos), sep = ",", quiet = TRUE))
wx <- which(c(FALSE, diff(s) < 0.1))
s[wx] <- (s[wx] + s[wx-1]) / 2
s[wx-1] <- NA
toString(na.omit(s))
}, by = 1:nrow(dataset)]
dataset
## C neg pos overlap
## 1: a 5, 7 5.05, 8 5.025, 7, 8
## 2: b 9 9
## 3: c 3, 4, 5 2.95, 4.2 2.975, 4, 4.2, 5