使用if条件修改R循环以在R中应用格式

时间:2018-12-26 17:01:49

标签: r lapply

我正在创建一个名为indexPoints的变量,其中包含通过某些条件的索引值的子集-

set.seed(1)
x = abs(rnorm(100,1))
y = abs(rnorm(100,1))
threshFC = 0.5

indexPoints=c()
seqVec = seq(1, length(x))
for (i in seq_along(seqVec)){
    fract = x[i]/y[I]
    fract[1] = NaN
    if (!is.nan(fract)){
        if(fract > (threshFC + 1) || fract < (1/(threshFC+1))){
            indexPoints = c(indexPoints, i)
        }
    }
}

我正在尝试使用更有效的方法(如apply方法(除sapply之外的任何方法))重新创建indexPoints。我开始如下所示的过程-

set.seed(1)
x = abs(rnorm(100,1))
y = abs(rnorm(100,1))
threshFC = 0.5

seqVec <- seq_along(x)
fract = x[seqVec]/y[seqVec]
fract[1] = NaN
vapply(fract, function(i){
    if (!is.nan(fract)){ if(fract > (threshFC + 1) || fract < (1/(threshFC+1))){ i}}
}, character(1))

但是,这种尝试会导致错误:

Error in vapply(fract, function(i) { : values must be length 1,
 but FUN(X[[1]]) result is length 0

如何继续修改代码以使其成为适用格式。注意:有时,fract变量包含NaN值,在上面的最小示例中,我使用“ fract [1] = NaN”来模仿。

1 个答案:

答案 0 :(得分:6)

您的代码有几个问题:

  1. 您告诉vapply,您希望内部代码返回character,但您唯一返回的是i,即numeric;
  2. 您仅在满足所有条件时才显式返回某项,这意味着如果条件并非都满足,您将不会返回任何内容……这与return(NULL)相同,后者也不是{{1} }(尝试character);
  3. 您显式设置了vapply(1:2, function(a) return(NULL), character(1)),然后测试了fract[1] = NaN,所以您将一无所获。和
  4. (很可能是拼写错误)您引用了!is.nan(fract)(大写的“ i”),这是错误的,除非在某处定义了y[I](这不再是语法错误,但现在是逻辑错误)。

如果我在您的I循环中修复了代码(删除了NaN分配),我会得到

for

如果我们真的想一次执行一次(建议不要这样做,请阅读下文),那么有几种方法:

  1. 使用indexPoints # [1] 3 4 5 6 10 11 12 13 14 15 16 18 20 21 25 26 28 29 30 31 32 34 35 38 39 # [26] 40 42 43 44 45 47 48 49 50 52 53 54 55 56 57 58 59 60 61 64 66 68 70 71 72 # [51] 74 75 77 78 79 80 81 82 83 86 88 89 90 91 92 93 95 96 97 98 99 仅返回条件为true的索引:

    Filter
  2. 正确使用indexPoints2 <- Filter(function(i) { fract <- x[i] / y[i] !is.nan(fract) && (fract > (threshFC+1) | fract < (1/(threshFC+1))) }, seq_along(seqVec)) identical(indexPoints, indexPoints2) # [1] TRUE ,以下列两种方式返回整数:

    vapply

    (请注意明确返回特定类型的NA,即indexPoints3 <- vapply(seq_along(seqVec), function(i) { fract <- x[i] / y[i] if (!is.nan(fract) && (fract > (threshFC+1) | fract < (1/(threshFC+1)))) i else NA_integer_ }, integer(1)) str(indexPoints3) # int [1:100] NA NA 3 4 5 6 NA NA NA 10 ... indexPoints3 <- indexPoints3[!is.na(indexPoints3)] identical(indexPoints, indexPoints3) # [1] TRUE ,以便NA_integer_感到高兴。)

  3. 如果索引符合条件,我们可以只返回vapply

    logical

但是实际上,绝对不需要使用logicalPoints4 <- vapply(seq_along(seqVec), function(i) { fract <- x[i] / y[i] !is.nan(fract) && (fract > (threshFC+1) | fract < (1/(threshFC+1))) }, logical(1)) head(logicalPoints4) # [1] FALSE FALSE TRUE TRUE TRUE TRUE identical(indexPoints, which(logicalPoints4)) # [1] TRUE 或任何vapply函数,因为可以很容易地(并且更有效地)将其作为向量进行检查:

apply

(如果您不使用fract <- x/y # all at once indexPoints5 <- which(!is.nan(fract) & (fract > (threshFC+1) | fract < (1/(threshFC+1)))) identical(indexPoints, indexPoints5) # [1] TRUE ,则会看到它为您提供了一个which向量,指示是否满足条件,类似于上面的logical的项目符号3。 )