首页 > 解决方案 > 如何编写嵌套的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

标签: r

解决方案


问题是您有 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

推荐阅读