替代 for 和 ifelse 循环 - 确定元素是否位于生成的置信区间内
Alternative to for and ifelse loops - determining whether elements lie within generated confidence intervals
我正在尝试重写我的代码以不包含任何 for 循环或 ifelse 循环。目的是提取包含 0 和 1 的矩阵,具体取决于变量 mu 和变量 cinterval - 如果 y0 落在第 95 个 CI,而 0 y0 落在第 95 个 CI 内,对于 y1 也是如此。对于多个模块,将对 y0 和 y1 重复此操作。
mu 包含 y0 和 y1 的值; cinterval 包含四行:
- lower 95th CI limit for y0
- upper 95th CI limit for y0
- lower 95th CI limit for y1
- upper 95th CI limit for y1
cinterval 可以编程为具有任意数量的模块:
cinterval.fn <- function(y0y1modules) {
matrix(c(y0results, y1results) nrow=4, ncol=no.of.modules, byrow=T) #simplified from true code
rownames(cinterval) <- c("y0 95LCI", "y0 95UCI", "y1 95LCI", "y1 95UCI")
colnames(cinterval) <- paste('module', 1:length(cinterval[1,]), sep='.')
return(cinterval)
}
> cinterval
module.1 module.2 module.3
y0 95LCI 2.434602 1.784056 1.751713
y0 95UCI 5.988160 6.519465 6.833455
y1 95LCI 3.778811 2.681708 2.805293
y1 95UCI 9.228941 9.716476 10.258412
mu 看起来像这样:
mu <- c(4, 8)
mu
y0 y1
4 8
我的密码是:
incinterval.fn <- function(cov.xy, mu, n1, dr) {
cinterval <- cintervaloutput.fn(cov.xy, mu, n1, dr) # Generates matrix with 95% CI values for y0 and y1 after modules
y0 <- NULL # Empty vector
for (module.no in 1:ncol(cinterval)) {
y0 <- cbind(y0, ifelse (cinterval[1, module.no] <= mu["y0"] || mu["y0"] <= cinterval[2, module.no], 1, 0))
} # If y0 inside CI, 1, else 0
y1 <- NULL # Empty vector
for (module.no in 1:ncol(cinterval)) {
y1 <- cbind(y1, ifelse (cinterval[3, module.no] <= mu["y1"] || mu["y1"] <= cinterval[4, module.no], 1, 0))
} # If y1 inside CI, 1, else 0
incinterval <- rbind(y0, y1) # Combines vectors
colnames(incinterval) <- paste('module', 1:length(cinterval[1,]), sep='.')
return(incinterval)
}
结果 incinterval 如下所示:
module.1 module.2 module.3
[y0] 1 1 1
[y1] 1 1 1
如果能提供更高效的编码来替换 for 和 ifelse,我们将不胜感激!我目前使用 2 个 for 和 ifeelse 循环。
示例数据:
cinterval <- data.frame(rbind(c(2.434602,1.784056,1.751713),
c(5.988160,6.519465,6.833455),
c(3.778811,2.681708,2.805293),
c(9.228941,9.716476,10.258412)),
row.names = c("y0 L","y0 U","y1 L","y1 U")
)
colnames(cinterval) <- paste0("module.",1:3)
mu <- c("y0" = 4, "y1" = 8)
您可以利用向量化并将单个值与向量进行比较
as.numeric(mu["y0"] >= cinterval[1,] & mu["y0"] <= cinterval[2,])
[1] 1 1 1
适用于 "y1"。
假设您的输入数据是这样创建的:
mu = c(y0 = 4, y1 = 8)
cinterval <-
data.frame(names = c("y0", "y0", "y1", "y1"),
CI = c("LCI", "UCI", "LCI", "UCI"),
module.1 = c(2.434602, 5.988160, 3.778811, 9.228941),
module.2 = c(1.784056, 6.519465, 2.681708, 9.716476),
module.3 = c(1.751713, 6.833455, 2.805293, 10.258412))
然后像这样的东西可能会做你想要的:
sapply(seq_along(mu),
function(y) {
cis <- cinterval[cinterval[["names"]] == names(mu)[y], -1:-2]
apply(cis, 2, function(ci) {
findInterval(mu[y], ci)
})
})
我不确定您在多大程度上依赖于您的数据结构,但我提出了一种不同的方法。
如果您以其他格式构建数据集,则可以轻松地将 incinterval
的结果写入附加变量。
新数据:
cinterval <- data.frame(year = c(0, 0, 0, 1, 1, 1),
LCI = c(2.434602, 1.784056, 1.751713, 3.778811, 2.681708, 2.805293),
UCI = c(5.988160, 6.519465, 6.833455, 9.228941, 9.716476, 10.258412),
module = c(1, 2, 3, 1, 2, 3)
)
> cinterval
year LCI UCI module
1 0 2.434602 5.988160 1
2 0 1.784056 6.519465 2
3 0 1.751713 6.833455 3
4 1 3.778811 9.228941 1
5 1 2.681708 9.716476 2
6 1 2.805293 10.258412 3
现在你定义mu
mu <- c("y0" = 4, "y1" = 8)
和 apply
使用 findInterval
对您的行进行简短的 ifelse
条件以获取包含您的结果的新列:
cinterval$inCI <- apply(cinterval, 1,
function(x) ifelse(x[1] == 0, findInterval(mu["y0"], x[2:3]),
findInterval(mu["y1"], x[2:3]))
)
你的输出:
year LCI UCI module inCI
1 0 2.434602 5.988160 1 1
2 0 1.784056 6.519465 2 1
3 0 1.751713 6.833455 3 1
4 1 3.778811 9.228941 1 1
5 1 2.681708 9.716476 2 1
6 1 2.805293 10.258412 3 1
请注意,如果 mu
值低于 CI,findInterval
将 return 为 0,如果在 CI 范围内,则为 1,如果低于 CI,则为 2高于 CI.
这在处理许多 years
时可能会变得很麻烦,但是可以根据需要包含尽可能多的 modules
。
感谢大家的建议和反馈。
我采纳了 Ape 的建议,因为它是最简单的。
代码现在用粗体文本更改为:
incinterval.fn <- function(cov.xy, mu, n1, dr) {
cinterval <- cintervaloutput.fn(cov.xy, mu, n1, dr) # Generates matrix with 95% CI values for y0 and y1 after treatment modules (can be any number of modules))
**incinterval <- rbind(as.numeric(mu["y0"] >= cinterval[1,] & mu["y0"] <= cinterval[2,]),
as.numeric(mu["y1"] >= cinterval[3,] & mu["y0"] <= cinterval[4,]))**
colnames(incinterval) <- paste('module', 1:length(cinterval[1,]), sep='.')
return(incinterval)
}
它没有使用 for 循环和 ifelse 循环,而是使用一种更简单的方法来回答问题,即使用比较运算符生成向量。
我正在尝试重写我的代码以不包含任何 for 循环或 ifelse 循环。目的是提取包含 0 和 1 的矩阵,具体取决于变量 mu 和变量 cinterval - 如果 y0 落在第 95 个 CI,而 0 y0 落在第 95 个 CI 内,对于 y1 也是如此。对于多个模块,将对 y0 和 y1 重复此操作。
mu 包含 y0 和 y1 的值; cinterval 包含四行:
- lower 95th CI limit for y0
- upper 95th CI limit for y0
- lower 95th CI limit for y1
- upper 95th CI limit for y1
cinterval 可以编程为具有任意数量的模块:
cinterval.fn <- function(y0y1modules) {
matrix(c(y0results, y1results) nrow=4, ncol=no.of.modules, byrow=T) #simplified from true code
rownames(cinterval) <- c("y0 95LCI", "y0 95UCI", "y1 95LCI", "y1 95UCI")
colnames(cinterval) <- paste('module', 1:length(cinterval[1,]), sep='.')
return(cinterval)
}
> cinterval
module.1 module.2 module.3
y0 95LCI 2.434602 1.784056 1.751713
y0 95UCI 5.988160 6.519465 6.833455
y1 95LCI 3.778811 2.681708 2.805293
y1 95UCI 9.228941 9.716476 10.258412
mu 看起来像这样:
mu <- c(4, 8)
mu
y0 y1
4 8
我的密码是:
incinterval.fn <- function(cov.xy, mu, n1, dr) {
cinterval <- cintervaloutput.fn(cov.xy, mu, n1, dr) # Generates matrix with 95% CI values for y0 and y1 after modules
y0 <- NULL # Empty vector
for (module.no in 1:ncol(cinterval)) {
y0 <- cbind(y0, ifelse (cinterval[1, module.no] <= mu["y0"] || mu["y0"] <= cinterval[2, module.no], 1, 0))
} # If y0 inside CI, 1, else 0
y1 <- NULL # Empty vector
for (module.no in 1:ncol(cinterval)) {
y1 <- cbind(y1, ifelse (cinterval[3, module.no] <= mu["y1"] || mu["y1"] <= cinterval[4, module.no], 1, 0))
} # If y1 inside CI, 1, else 0
incinterval <- rbind(y0, y1) # Combines vectors
colnames(incinterval) <- paste('module', 1:length(cinterval[1,]), sep='.')
return(incinterval)
}
结果 incinterval 如下所示:
module.1 module.2 module.3
[y0] 1 1 1
[y1] 1 1 1
如果能提供更高效的编码来替换 for 和 ifelse,我们将不胜感激!我目前使用 2 个 for 和 ifeelse 循环。
示例数据:
cinterval <- data.frame(rbind(c(2.434602,1.784056,1.751713),
c(5.988160,6.519465,6.833455),
c(3.778811,2.681708,2.805293),
c(9.228941,9.716476,10.258412)),
row.names = c("y0 L","y0 U","y1 L","y1 U")
)
colnames(cinterval) <- paste0("module.",1:3)
mu <- c("y0" = 4, "y1" = 8)
您可以利用向量化并将单个值与向量进行比较
as.numeric(mu["y0"] >= cinterval[1,] & mu["y0"] <= cinterval[2,])
[1] 1 1 1
适用于 "y1"。
假设您的输入数据是这样创建的:
mu = c(y0 = 4, y1 = 8)
cinterval <-
data.frame(names = c("y0", "y0", "y1", "y1"),
CI = c("LCI", "UCI", "LCI", "UCI"),
module.1 = c(2.434602, 5.988160, 3.778811, 9.228941),
module.2 = c(1.784056, 6.519465, 2.681708, 9.716476),
module.3 = c(1.751713, 6.833455, 2.805293, 10.258412))
然后像这样的东西可能会做你想要的:
sapply(seq_along(mu),
function(y) {
cis <- cinterval[cinterval[["names"]] == names(mu)[y], -1:-2]
apply(cis, 2, function(ci) {
findInterval(mu[y], ci)
})
})
我不确定您在多大程度上依赖于您的数据结构,但我提出了一种不同的方法。
如果您以其他格式构建数据集,则可以轻松地将 incinterval
的结果写入附加变量。
新数据:
cinterval <- data.frame(year = c(0, 0, 0, 1, 1, 1),
LCI = c(2.434602, 1.784056, 1.751713, 3.778811, 2.681708, 2.805293),
UCI = c(5.988160, 6.519465, 6.833455, 9.228941, 9.716476, 10.258412),
module = c(1, 2, 3, 1, 2, 3)
)
> cinterval
year LCI UCI module
1 0 2.434602 5.988160 1
2 0 1.784056 6.519465 2
3 0 1.751713 6.833455 3
4 1 3.778811 9.228941 1
5 1 2.681708 9.716476 2
6 1 2.805293 10.258412 3
现在你定义mu
mu <- c("y0" = 4, "y1" = 8)
和 apply
使用 findInterval
对您的行进行简短的 ifelse
条件以获取包含您的结果的新列:
cinterval$inCI <- apply(cinterval, 1,
function(x) ifelse(x[1] == 0, findInterval(mu["y0"], x[2:3]),
findInterval(mu["y1"], x[2:3]))
)
你的输出:
year LCI UCI module inCI
1 0 2.434602 5.988160 1 1
2 0 1.784056 6.519465 2 1
3 0 1.751713 6.833455 3 1
4 1 3.778811 9.228941 1 1
5 1 2.681708 9.716476 2 1
6 1 2.805293 10.258412 3 1
请注意,如果 mu
值低于 CI,findInterval
将 return 为 0,如果在 CI 范围内,则为 1,如果低于 CI,则为 2高于 CI.
这在处理许多 years
时可能会变得很麻烦,但是可以根据需要包含尽可能多的 modules
。
感谢大家的建议和反馈。
我采纳了 Ape 的建议,因为它是最简单的。
代码现在用粗体文本更改为:
incinterval.fn <- function(cov.xy, mu, n1, dr) {
cinterval <- cintervaloutput.fn(cov.xy, mu, n1, dr) # Generates matrix with 95% CI values for y0 and y1 after treatment modules (can be any number of modules))
**incinterval <- rbind(as.numeric(mu["y0"] >= cinterval[1,] & mu["y0"] <= cinterval[2,]),
as.numeric(mu["y1"] >= cinterval[3,] & mu["y0"] <= cinterval[4,]))**
colnames(incinterval) <- paste('module', 1:length(cinterval[1,]), sep='.')
return(incinterval)
}
它没有使用 for 循环和 ifelse 循环,而是使用一种更简单的方法来回答问题,即使用比较运算符生成向量。