我正在创建一个名为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”来模仿。
答案 0 :(得分:6)
您的代码有几个问题:
vapply
,您希望内部代码返回character
,但您唯一返回的是i
,即numeric
; return(NULL)
相同,后者也不是{{1} }(尝试character
); vapply(1:2, function(a) return(NULL), character(1))
,然后测试了fract[1] = NaN
,所以您将一无所获。和!is.nan(fract)
(大写的“ i”),这是错误的,除非在某处定义了y[I]
(这不再是语法错误,但现在是逻辑错误)。 如果我在您的I
循环中修复了代码(删除了NaN
分配),我会得到
for
如果我们真的想一次执行一次(建议不要这样做,请阅读下文),那么有几种方法:
使用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
正确使用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_
感到高兴。)
如果索引符合条件,我们可以只返回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。 )