【问题标题】:If else statement for a list with matrices带有矩阵的列表的 if else 语句
【发布时间】:2015-07-07 18:44:09
【问题描述】:

我正在学习如何正确设置循环,但仍然在努力使用正确的索引和语法。 下面我有两个矩阵的列表,每个矩阵 2 列 x 3 行。 我想查看每个矩阵中的第二列,如果 x>0.50,则理想情况下创建一个值为 1 的新列,否则 = 0。两种方法都将非常感谢帮助,它应该可以帮助我学习。此外,如果您知道在高维列表中构造循环的任何良好参考,我们将不胜感激。非常感谢。

a <- c(0.1,0.2,0.3)
b <- c(0.8,0.2,0.5)
c <- c(0.4,0.9,1.0)
d <- c(0.7,0.9,0.2)
ab <- cbind(a,b)
cd <- cbind(c,d)
abcd <- list(ab,cd)

presabs <- vector("list",ncol(y))

# Trying lapply but indexing something wrong
res <- lapply(abcd, function(x) if (x[,2]>0.5) {1} else {0})

# Other method also not working:

for (i in 1:length(abcd))
        for (j in 1:length(a)){
                {
                if(abc[[i]][j]>0.50){
                        presabs[j] <- 1
                } else {
                        presabs[j] <- 0
                }
        }
}

【问题讨论】:

    标签: r list if-statement


    【解决方案1】:

    您可以使用ifelse,或者在这种情况下也不需要它。 OP 的问题是创建一个二进制变量作为第三列。这可以使用多种变体来完成,

    lapply(abcd, function(x) cbind(x,new= +(x[,2]>0.5)))
    

    lapply(abcd, function(x) cbind(x,new= (x[,2]>0.5)+0L))
    

    或者

    lapply(abcd, function(x) cbind(x,new= (x[,2]>0.5)*1))
    

    或者

    lapply(abcd, function(x) cbind(x,new= as.integer(x[,2]>0.5)))
    

    如果要更改的值不同,例如

    a <- 3
    b <- 2
    lapply(abcd, function(x) cbind(x, new= c(a, b)[(x[,2] > 0.5)+1L]))
    

    基准测试

    set.seed(25)
    abcd1 <- lapply(1:60, function(i) matrix(rnorm(1e5*2), ncol=2))
    viaChris <- function() lapply(abcd1, function(x) f(x, a=1, b=0, thresh =.5))
    akrun <- function() lapply(abcd1, function(x) cbind(x, lab= +(x[,2] >0.5)))
    
    system.time(viaChris())
    # user  system elapsed 
    #1.683   0.000   1.444 
    system.time(akrun())
    # user  system elapsed 
    # 0.481   0.000   0.322 
    
    library(microbenchmark)
    microbenchmark(akrun(), viaChris(), unit='relative', times=20L)
    #Unit: relative
    #     expr      min       lq     mean   median       uq      max neval cld
    #   akrun() 1.000000 1.000000 1.000000 1.000000 1.000000 1.000000    20  a 
    #viaChris() 3.726728 3.459581 3.475673 3.488114 3.400262 3.445557    20   b
    

    【讨论】:

      【解决方案2】:

      上述答案有效,因为逻辑值被强制转换为 1(TRUE)和 0(FALSE)。更通用的解决方案可能类似于:

      lapply(abcd, function(x) cbind(x, ifelse(x[, 2] > .5, a, b)))
      

      其中ab 是您可以指定的数值。我们甚至可以更笼统。例如:

      ##  Define a general function that adds a new column of values
      ##  based on whether or not the values in the i'th column of the 
      ##  matrix exceeds a threshold.
      f = function(x, a, b, thresh, i = 2) 
             cbind(x, lab = ifelse(x[, i] > thresh, a, b))
      
      ##  Apply the function above to each matrix in the list 'abcd', with
      ##  a = 1, b = 0, and thresh = .5.
      lapply(abcd, function(x) f(x, a = 1, b = 0, thresh = .5))
      

      【讨论】: