r - 使用 if 条件修改 for 循环以在 R 中应用格式
问题描述
我正在创建一个名为 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)
}
}
}
我正在尝试使用更有效的方法重新创建 indexPoints,例如应用方法(除了 sapply 之外的任何方法)。我开始了如下所示的过程 -
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”来模仿上面的最小示例。
解决方案
您的代码有几个问题:
- 您告诉
vapply
您希望内部代码返回 acharacter
,但您返回的唯一i
内容是numeric
; - 只有当所有条件都满足时,你才显式地返回一些东西,这意味着如果条件不是很好,你什么都不返回......这与
return(NULL)
which is also notcharacter
(tryvapply(1:2, function(a) return(NULL), character(1))
); - 你明确地设置
fract[1] = NaN
然后测试!is.nan(fract)
,所以你永远不会得到任何东西;和 - (可能是错字)您引用
y[I]
(大写“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
如果我们真的想一次做一个(我建议不要这样做,请阅读下文),那么有几种方法:
用于
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
正确使用,无论哪种方式都返回一个整数: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 的显式返回,即
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 logicalPoints4
。)
推荐阅读
- php - 从特定 URL 中删除 .php 扩展名
- node.js - 如何为本地网站提供 PWA 支持?
- java - 在Android推送通知中关闭应用程序时,我们如何在点击托盘时获取有效负载数据?
- html - 嵌入的 youtube 视频无法在谷歌浏览器中播放
- jmeter - 如何使用 JMeter 工具理想地加载测试?
- java - 将参数从验证传递到休眠验证器中的自定义验证器
- java - Java Minimax tic-tac-toe 游戏未按预期工作
- laravel - 未定义变量:文件(查看:\resources\views\home.blade.php)
- python - 如何解决 ValueError:传递值的形状为 (3, 4),索引暗示 (4, 4)
- java - Spring Boot 中的 CORS 策略冲突