替代for和ifelse循环 - 确定元素是否位于生成的置信区间内

时间:2017-11-16 08:53:15

标签: r for-loop if-statement confidence-interval

我试图重写我的代码,不包含任何for循环或ifelse循环。目的是根据变量 mu 和变量 cinterval 提取包含0和1的矩阵 - 如果y0落在其第95个CI内,则生成1,并且0 y0落在它的第95个CI,同样适用于y1。对于许多模块,y0和y1都会重复这一过程。

mu 包含y0和y1的值; cinterval 包含四行:

  
      
  1. y0
  2. 的第95个CI限制   
  3. y0
  4. 的第95个CI限制   
  5. y1
  6. 的第95个CI限制   
  7. y1的第95个CI限制
  8.   

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

任何有关更高效编码以替换和ifelse的帮助将不胜感激!我目前使用2 for和ifeelse循环。

4 个答案:

答案 0 :(得分:1)

示例数据:

as.numeric(mu["y0"] >= cinterval[1,] & mu["y0"] <= cinterval[2,])

[1] 1 1 1

您可以利用矢量化并将单个值与矢量

进行比较
{{1}}

相应地为&#34; y1&#34;。

工作

答案 1 :(得分:0)

假设输入数据的创建类似于:

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)
          })

})

答案 2 :(得分:0)

我不确定您对数据结构的依赖程度,但我提出了不同的方法。

如果您以其他格式构建数据集,则可以轻松地将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为您的行添加

ifelse一个简短的findInterval条件,以获得包含结果的新列:

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

请注意,如果findInterval值低于CI,mu将返回0,如果它在其中,则返回1,如果它高于CI,则返回2。

在处理许多years时,这可能会变得很麻烦,但要包含尽可能多的modules非常强大。

答案 3 :(得分:0)

感谢大家的建议和反馈。

我接受了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循环,而是使用更简单的方法来回答问题,并使用比较运算符生成向量。