r - 如何编写嵌套的for循环,以便内部循环不会覆盖第一个循环值
问题描述
Stackoverflow 上的新海报,但长期观看者。我找不到任何以前的帖子来解决我的具体问题。
基本上,我正在努力解决如何使用嵌套for
循环来解决我的问题。问题是变量和结果的数量会随着用例的变化而变化,所以我想要一个对各种排列灵活的解决方案。我不确定这apply
会对我有帮助,因为我事先不知道在任何给定的用例中会存在多少变量和结果。
目标是对变量是否正确预测结果进行分类(tp = 真阳性等)。
问题是内部循环导致外部循环值被覆盖,但我想要的是outcome
每个独立地评估variable
一次。不确定最好的方法是什么,任何建议表示赞赏。
#Repex code
#Generate variable
variable <- c(1,2,3)
df <- as.data.frame(matrix(0, ncol = 0, nrow = 30))
for(i in 1:length(variable)){
df[,c(paste0("variable",variable[i]))]<-as.vector(sample(c(0,1), replace=TRUE, size=30))
}
df
#Generate outcome
outcome <- c(1,2,3)
df2 <- as.data.frame(matrix(0, ncol = 0, nrow = 30))
for(i in 1:length(outcome)){
df2[,c(paste0("outcome",outcome[i]))]<-as.vector(sample(c(0,1), replace=TRUE, size=30))
}
df2
#Generate performance metrics of outcome and predictor
for (i in variable){
for(j in 1:length(df2)){
df[, c(paste0("tp.",variable[i]))] <- as.vector(ifelse(df[, c(paste0("variable",variable[i]))]==1 & df2[j]==1,1,0))
df[, c(paste0("tn.",variable[i]))] <- as.vector(ifelse(df[, c(paste0("variable",variable[i]))]==0 & df2[j]==0,1,0))
df[, c(paste0("fp.",variable[i]))] <- as.vector(ifelse(df[, c(paste0("variable",variable[i]))]==1 & df2[j]==0,1,0))
df[, c(paste0("fn.",variable[i]))] <- as.vector(ifelse(df[, c(paste0("variable",variable[i]))]==0 & df2[j]==1,1,0))
}
}
df
#bind the data for comparison and spot checking
df3 <- cbind(df2,df)
#here we see that only the final inner loop data are correct
df3
解决方案
问题是您有 3 个不同variable
的 s 要与 3 个不同outcome
的 s 进行比较,因此您要进行 9 次比较。但是,由于您仅根据 标记列variable
,因此您只有三个唯一的数字后缀(每个值一个i
)粘贴到每个统计信息(tp、tn、fp 和 fn)上。因此,您只有 12 个不同的列名。
您绝不会根据变量和结果来标记列。这意味着每次您的内部循环递增到下一个结果变量时,您都会覆盖df
您在循环的前一次迭代中编写的列。
在任何情况下,除非您同时使用变量编号和结果编号来标记列,否则您打算如何跟踪您正在进行的比较?
所以你可以这样做:
for (i in variable)
{
V <- c(paste0("variable", i))
for(j in seq_along(df2))
{
comp <- paste0(i, ".vs.", j)
df[paste0("tp.", comp)] <- as.numeric(df[V] == 1 & df2[j] == 1)
df[paste0("tn.", comp)] <- as.numeric(df[V] == 0 & df2[j] == 0)
df[paste0("fp.", comp)] <- as.numeric(df[V] == 1 & df2[j] == 0)
df[paste0("fn.", comp)] <- as.numeric(df[V] == 0 & df2[j] == 1)
}
}
df3 <- cbind(df2, df)
这将为您提供您正在寻找的结构。这是一个大型数据框,因此我们将通过以下方式查看它str
:
str(df3)
#> 'data.frame': 30 obs. of 42 variables:
#> $ outcome1 : num 0 1 1 1 1 0 1 0 1 1 ...
#> $ outcome2 : num 0 0 0 0 1 0 0 1 1 1 ...
#> $ outcome3 : num 1 1 0 0 0 0 0 0 1 0 ...
#> $ variable1: num 0 1 0 0 1 1 0 1 1 1 ...
#> $ variable2: num 1 1 0 0 0 0 0 0 0 0 ...
#> $ variable3: num 1 0 0 0 1 0 0 1 0 0 ...
#> $ tp.1.vs.1: num 0 1 0 0 1 0 0 0 1 1 ...
#> $ tn.1.vs.1: num 1 0 0 0 0 0 0 0 0 0 ...
#> $ fp.1.vs.1: num 0 0 0 0 0 1 0 1 0 0 ...
#> $ fn.1.vs.1: num 0 0 1 1 0 0 1 0 0 0 ...
#> $ tp.1.vs.2: num 0 0 0 0 1 0 0 1 1 1 ...
#> $ tn.1.vs.2: num 1 0 1 1 0 0 1 0 0 0 ...
#> $ fp.1.vs.2: num 0 1 0 0 0 1 0 0 0 0 ...
#> $ fn.1.vs.2: num 0 0 0 0 0 0 0 0 0 0 ...
#> $ tp.1.vs.3: num 0 1 0 0 0 0 0 0 1 0 ...
#> $ tn.1.vs.3: num 0 0 1 1 0 0 1 0 0 0 ...
#> $ fp.1.vs.3: num 0 0 0 0 1 1 0 1 0 1 ...
#> $ fn.1.vs.3: num 1 0 0 0 0 0 0 0 0 0 ...
#> $ tp.2.vs.1: num 0 1 0 0 0 0 0 0 0 0 ...
#> $ tn.2.vs.1: num 0 0 0 0 0 1 0 1 0 0 ...
#> $ fp.2.vs.1: num 1 0 0 0 0 0 0 0 0 0 ...
#> $ fn.2.vs.1: num 0 0 1 1 1 0 1 0 1 1 ...
#> $ tp.2.vs.2: num 0 0 0 0 0 0 0 0 0 0 ...
#> $ tn.2.vs.2: num 0 0 1 1 0 1 1 0 0 0 ...
#> $ fp.2.vs.2: num 1 1 0 0 0 0 0 0 0 0 ...
#> $ fn.2.vs.2: num 0 0 0 0 1 0 0 1 1 1 ...
#> $ tp.2.vs.3: num 1 1 0 0 0 0 0 0 0 0 ...
#> $ tn.2.vs.3: num 0 0 1 1 1 1 1 1 0 1 ...
#> $ fp.2.vs.3: num 0 0 0 0 0 0 0 0 0 0 ...
#> $ fn.2.vs.3: num 0 0 0 0 0 0 0 0 1 0 ...
#> $ tp.3.vs.1: num 0 0 0 0 1 0 0 0 0 0 ...
#> $ tn.3.vs.1: num 0 0 0 0 0 1 0 0 0 0 ...
#> $ fp.3.vs.1: num 1 0 0 0 0 0 0 1 0 0 ...
#> $ fn.3.vs.1: num 0 1 1 1 0 0 1 0 1 1 ...
#> $ tp.3.vs.2: num 0 0 0 0 1 0 0 1 0 0 ...
#> $ tn.3.vs.2: num 0 1 1 1 0 1 1 0 0 0 ...
#> $ fp.3.vs.2: num 1 0 0 0 0 0 0 0 0 0 ...
#> $ fn.3.vs.2: num 0 0 0 0 0 0 0 0 1 1 ...
#> $ tp.3.vs.3: num 1 0 0 0 0 0 0 0 0 0 ...
#> $ tn.3.vs.3: num 0 0 1 1 0 1 1 0 0 1 ...
#> $ fp.3.vs.3: num 0 0 0 0 1 0 0 1 0 0 ...
#> $ fn.3.vs.3: num 0 1 0 0 0 0 0 0 1 0 ...
另一种(也许更明智)的方法是使用 3 个数据框,每个变量一个,每个有 12 列(三组 tp、tn、fp、fn)。您可以使用以下方法轻松完成此操作lapply
:
df_list <- lapply(df, function(x)
{
dfs <- list()
for(j in seq_along(df2))
{
dfs[[j]] <- data.frame(ifelse(x == 1 & df2[j] == 1, 1, 0),
ifelse(x == 0 & df2[j] == 0, 1, 0),
ifelse(x == 1 & df2[j] == 0, 1, 0),
ifelse(x == 0 & df2[j] == 1, 1, 0))
}
setNames(do.call("cbind", dfs),
paste0(c("tp.", "tn.", "fp.", "fn."), rep(seq_along(df2), each = 4)))
})
这给了你:
df_list
#> $variable1
#> tp.1 tn.1 fp.1 fn.1 tp.2 tn.2 fp.2 fn.2 tp.3 tn.3 fp.3 fn.3
#> 1 0 1 0 0 0 1 0 0 0 0 0 1
#> 2 1 0 0 0 0 0 1 0 1 0 0 0
#> 3 0 0 0 1 0 1 0 0 0 1 0 0
#> 4 0 0 0 1 0 1 0 0 0 1 0 0
#> 5 1 0 0 0 1 0 0 0 0 0 1 0
#> 6 0 0 1 0 0 0 1 0 0 0 1 0
#> 7 0 0 0 1 0 1 0 0 0 1 0 0
#> 8 0 0 1 0 1 0 0 0 0 0 1 0
#> 9 1 0 0 0 1 0 0 0 1 0 0 0
#> 10 1 0 0 0 1 0 0 0 0 0 1 0
#> 11 0 1 0 0 0 0 0 1 0 0 0 1
#> 12 0 0 1 0 1 0 0 0 1 0 0 0
#> 13 0 0 0 1 0 1 0 0 0 1 0 0
#> 14 0 1 0 0 0 0 0 1 0 0 0 1
#> 15 0 0 0 1 0 1 0 0 0 0 0 1
#> 16 0 1 0 0 0 1 0 0 0 0 0 1
#> 17 0 0 1 0 1 0 0 0 1 0 0 0
#> 18 0 0 1 0 0 0 1 0 0 0 1 0
#> 19 0 0 1 0 0 0 1 0 0 0 1 0
#> 20 1 0 0 0 0 0 1 0 1 0 0 0
#> 21 0 1 0 0 0 1 0 0 0 1 0 0
#> 22 1 0 0 0 0 0 1 0 1 0 0 0
#> 23 0 0 0 1 0 1 0 0 0 0 0 1
#> 24 0 0 0 1 0 1 0 0 0 0 0 1
#> 25 0 0 1 0 0 0 1 0 0 0 1 0
#> 26 0 0 1 0 0 0 1 0 0 0 1 0
#> 27 1 0 0 0 1 0 0 0 0 0 1 0
#> 28 0 0 1 0 0 0 1 0 1 0 0 0
#> 29 0 0 0 1 0 1 0 0 0 1 0 0
#> 30 0 0 1 0 0 0 1 0 0 0 1 0
#>
#> $variable2
#> tp.1 tn.1 fp.1 fn.1 tp.2 tn.2 fp.2 fn.2 tp.3 tn.3 fp.3 fn.3
#> 1 0 0 1 0 0 0 1 0 1 0 0 0
#> 2 1 0 0 0 0 0 1 0 1 0 0 0
#> 3 0 0 0 1 0 1 0 0 0 1 0 0
#> 4 0 0 0 1 0 1 0 0 0 1 0 0
#> 5 0 0 0 1 0 0 0 1 0 1 0 0
#> 6 0 1 0 0 0 1 0 0 0 1 0 0
#> 7 0 0 0 1 0 1 0 0 0 1 0 0
#> 8 0 1 0 0 0 0 0 1 0 1 0 0
#> 9 0 0 0 1 0 0 0 1 0 0 0 1
#> 10 0 0 0 1 0 0 0 1 0 1 0 0
#> 11 0 1 0 0 0 0 0 1 0 0 0 1
#> 12 0 0 1 0 1 0 0 0 1 0 0 0
#> 13 0 0 0 1 0 1 0 0 0 1 0 0
#> 14 0 0 1 0 1 0 0 0 1 0 0 0
#> 15 1 0 0 0 0 0 1 0 1 0 0 0
#> 16 0 0 1 0 0 0 1 0 1 0 0 0
#> 17 0 1 0 0 0 0 0 1 0 0 0 1
#> 18 0 0 1 0 0 0 1 0 0 0 1 0
#> 19 0 0 1 0 0 0 1 0 0 0 1 0
#> 20 1 0 0 0 0 0 1 0 1 0 0 0
#> 21 0 1 0 0 0 1 0 0 0 1 0 0
#> 22 0 0 0 1 0 1 0 0 0 0 0 1
#> 23 0 0 0 1 0 1 0 0 0 0 0 1
#> 24 1 0 0 0 0 0 1 0 1 0 0 0
#> 25 0 0 1 0 0 0 1 0 0 0 1 0
#> 26 0 0 1 0 0 0 1 0 0 0 1 0
#> 27 1 0 0 0 1 0 0 0 0 0 1 0
#> 28 0 0 1 0 0 0 1 0 1 0 0 0
#> 29 0 0 0 1 0 1 0 0 0 1 0 0
#> 30 0 0 1 0 0 0 1 0 0 0 1 0
#>
#> $variable3
#> tp.1 tn.1 fp.1 fn.1 tp.2 tn.2 fp.2 fn.2 tp.3 tn.3 fp.3 fn.3
#> 1 0 0 1 0 0 0 1 0 1 0 0 0
#> 2 0 0 0 1 0 1 0 0 0 0 0 1
#> 3 0 0 0 1 0 1 0 0 0 1 0 0
#> 4 0 0 0 1 0 1 0 0 0 1 0 0
#> 5 1 0 0 0 1 0 0 0 0 0 1 0
#> 6 0 1 0 0 0 1 0 0 0 1 0 0
#> 7 0 0 0 1 0 1 0 0 0 1 0 0
#> 8 0 0 1 0 1 0 0 0 0 0 1 0
#> 9 0 0 0 1 0 0 0 1 0 0 0 1
#> 10 0 0 0 1 0 0 0 1 0 1 0 0
#> 11 0 1 0 0 0 0 0 1 0 0 0 1
#> 12 0 1 0 0 0 0 0 1 0 0 0 1
#> 13 1 0 0 0 0 0 1 0 0 0 1 0
#> 14 0 1 0 0 0 0 0 1 0 0 0 1
#> 15 0 0 0 1 0 1 0 0 0 0 0 1
#> 16 0 0 1 0 0 0 1 0 1 0 0 0
#> 17 0 0 1 0 1 0 0 0 1 0 0 0
#> 18 0 1 0 0 0 1 0 0 0 1 0 0
#> 19 0 1 0 0 0 1 0 0 0 1 0 0
#> 20 1 0 0 0 0 0 1 0 1 0 0 0
#> 21 0 0 1 0 0 0 1 0 0 0 1 0
#> 22 0 0 0 1 0 1 0 0 0 0 0 1
#> 23 1 0 0 0 0 0 1 0 1 0 0 0
#> 24 0 0 0 1 0 1 0 0 0 0 0 1
#> 25 0 1 0 0 0 1 0 0 0 1 0 0
#> 26 0 1 0 0 0 1 0 0 0 1 0 0
#> 27 1 0 0 0 1 0 0 0 0 0 1 0
#> 28 0 0 1 0 0 0 1 0 1 0 0 0
#> 29 1 0 0 0 0 0 1 0 0 0 1 0
#> 30 0 0 1 0 0 0 1 0 0 0 1 0
推荐阅读
- javascript - 页面刷新时的 JavaScript 警告框
- javascript - ajax成功功能无法更改按钮文本
- angular - 无法从 HTML EventListener 调用 Angular 6 服务
- c - 我使用代码块编写了一个单线程程序,但在任务管理器中它显示该程序正在使用 2 个线程?
- node.js - 触发错误处理时,应用程序崩溃
- node.js - 如何在 MongoDB 中插入许多数据
- sql - 更新sql时替换字符串
- maven - Java 11 Eclipse 找到自动模块,Maven 没有
- scala - 简化方法:将两个选项合并为一个结果
- json - SLC 代码未填补所有 Landsat 7 SR 空白