如果条件更快的话

时间:2016-01-30 07:13:13

标签: r if-statement matrix apply

我试图让这个功能起作用并且运行得更快。它将矩阵作为输入,并检查x和y是否都大于0但小于10.运行得更快也是关键,因为它目前需要很长时间才能使用所有这些条件语句

m 
   x  y
B -1 -1
C 50 11
D 50  5
A 51 10

val_10 = 10
myfun(m, val_10)

并且输出应该看起来像这样

     [,1] [,2]
[1,]    0   0
[2,]   10   10
[3,]   10    5
[4,]   10   10

但它看起来像这样

     [,1] [,2]
[1,]    0   -1
[2,]   10   11
[3,]   10    5
[4,]   10   10

m [1,2]应为0,输出中m [2,2]应为10

myfun看起来像这样

myfun = function(m, val_10){
v = matrix(NA, nrow = nrow(m), ncol = 2)
for (i in 1:nrow(m) ) {
    old = m[i, ]

    #check if smaller than 0
    if (m[i,1] < 0) {
        m[i, ] = c(0, old[2])
    }

    #check if bigger than val_10
    else if (m[i,1] > val_10 ){ 
        m[i, ] = c(val_10, old[2] )
    }

    #check if smaller than 0
    else if (m[i, 2] < 0){
        m[i, ] = c(old[1], 0)
    }

    #check if bigger than val_10
    else if (m[i, 2] > val_10){
        m[i, ] = c(old[1], val_10 )
    }

    v[i,] = m[i, ]
}
return(v)
}

修改

这适用于示例矩阵,但不适用于其他示例。这个矩阵给了我价值&#34; 5&#34;对于整个y列

   x y
B 49 6
C 50 7
D 50 5
A 51 6

`dim<-`(c(0,5,val_10)[(findInterval(m, c(5, val_10))+1L)], dim(m))

     [,1] [,2]
[1,]   10    5
[2,]   10    5
[3,]   10    5
[4,]   10    5

3 个答案:

答案 0 :(得分:4)

一个简单的选项可能包括逻辑子集和替换,如下所示:

m[m < 0] <- 0
m[m > 10] <- 10
#> m
#   x  y
#B  0  0
#C 10 10
#D 10  5
#A 10 10

在这种向量化方法中,避免使用任何明确的ififelse语句。

如果要将其包装到函数中,可以使用

my_fun <- function(m,val) {m[m > val] <- val; m[m < 0] <- 0; return(m)}     

数据:

m <- structure(c(-1L, 50L, 50L, 51L, -1L, 11L, 5L, 10L), .Dim = c(4L,2L), 
                    .Dimnames = list(c("B", "C", "D", "A"), c("x", "y")))

答案 1 :(得分:1)

我们可以尝试findInterval

myfun <- function(mat, val){
 i1 <- findInterval(mat, c(0, val))
 `dim<-`(ifelse(i1==1, mat, c(0,val)[i1]), dim(mat))
}

myfun(m, 10)
#     [,1] [,2]
#[1,]   10    0
#[2,]   10   10
#[3,]   10    5
#[4,]   10   10

使用新示例

myfun(m2, 10)
#     [,1] [,2]
#[1,]   10    6
#[2,]   10    7
#[3,]   10    5
#[4,]   10    6

数据

m <- structure(c(-1L, 50L, 50L, 51L, -1L, 11L, 5L, 10L),
.Dim = c(4L, 
2L), .Dimnames = list(c("B", "C", "D", "A"), c("x", "y")))

m2 <- cbind(c(49, 50, 50, 51), c(6, 7, 5, 6))

答案 2 :(得分:1)

这个让我得到你只看ifelse函数的结果:

in_vec <- c(-1,50,50,51,-1,11,5,10)
mtx <- matrix(in_vec, nrow = 4, byrow = F)
my_val <- 10
ifelse(mtx < 0, 0, ifelse(mtx >= my_val, my_val, mtx))

通常,这对于使用嵌套的ifelse函数来说是一个相当不错的案例。我当然在工作中定期使用该函数,对于像这样的矢量化任务来说,这比一个繁琐的for-loop / if-else组合要简单得多。