【问题标题】:How does one enter the varying statement in a loop of a function requiring two input statements?如何在需要两个输入语句的函数循环中输入变化语句?
【发布时间】:2018-04-19 16:57:18
【问题描述】:

我是 R 的新手并且已经搜索过,但没有找到可以满足我尝试编写脚本的需求的查询/答案。我正在尝试循环 pROC 包中的 roc() 函数来计算多个 ROC 曲线的几个参数。我的数据看起来像这样,只有更多的行和列(我的 df 在下面的代码中称为 ROCTest5):

Outcome A B C D E BiOutcome <chr> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> Good 21151. 4966. 1943. 646. 277. 1. Good 46278. 9408. 2810. 906. 856. 1. Poor 4717. 2153. 758. 215. 148. 0. Poor 14488. 4661. 1167. 530. 299. 0.

如果我手动运行每个 ROC 分析,这不适用于更大的数据集,我将使用以下代码:

ROCvirus = roc(ROCTest5$Outcome,
            ROCTest5$A,
            plot=TRUE, grid=TRUE,
            print.auc=TRUE, show.thres=TRUE)

aucA = auc(ROCvirus, as.vector=T)

ROCViCoorBest = coords(ROCvirus,"best",input=c("threshold", "specificity", "sensitivity", "accuracy",
                                       "tn", "tp", "fn", "fp", "npv", "ppv"), as.list=T)

我一直试图用于创建循环的代码如下所示:

library(pROC)

rocData = NULL
for(i in ROCTest5[A:E]){
 rocValue = roc(ROCTest5$Outcome,
             ROCTest5[[i in A:E]], #issue is here!
             plot=FALSE, auc=TRUE)
rocCoordi = coords(rocValue,"best",input=c("threshold", "specificity", "sensitivity", "accuracy",
                                         "tn", "tp", "fn", "fp", "npv", "ppv"))
rocValue = rbind(rocValue,rocCoordi)
rocData = cbind(rocData,rocValue)
}

此代码不起作用,因为我没有正确输入第二个输入参数的语句,这是每次循环迭代都会更改的参数。我尝试了几种不同的方法来做到这一点,例如使用第二个“for”语句,但无法使脚本正常工作。我还尝试使用“应用”功能编写脚本,但遇到了同样的一般问题。 如何在需要两个输入语句的函数循环中输入变化语句? 如果您对代码有更正,或者为此采用完全不同的方法来实现我的目标,我会全力以赴。提前谢谢!

【问题讨论】:

  • 你需要使用不同的ins。在您的ROCTest5[[i in A:E]] 行上,您应该将其更改为ROCTest5[[i %in% A:E]],这实际上是在下面调用match 函数。
  • 谢谢 C.Braun,这是有道理的。但是,我的代码中肯定有另一个错误,因为即使在添加 %in% 之后我也会收到错误:Error in check_names_df(i, x) : object 'A' not found

标签: r loops for-loop apply roc


【解决方案1】:

解决此问题的更好方法是使用 apply 语句。在基础 R 中,您可以通过调用来做到这一点

list_of_results <- lapply(LETTERS[1:5], function(x) {
  ROCvirus = roc(ROCTest5$Outcome,
        ROCTest5[[x]],
        plot=TRUE, grid=TRUE,
        print.auc=TRUE, show.thres=TRUE)
  auc_result <- auc(ROCvirus, as.vector=T)
  ROCViCoorBest = coords(ROCvirus,"best",ret=c("threshold", "specificity", "sensitivity", "accuracy",
                                       "tn", "tp", "fn", "fp", "npv", "ppv"), as.list=T)
  list(ROCvirus = ROCvirus, auc = auc_result, ROCViCoorBest = ROCViCoorBest)
})

它应该返回一个长度为 5 的列表,A 的结果在第一个条目中,... 到 E 的结果在第 5 个条目中。

函数的内容直接取自您添加的第一个代码块。要使用列表,您可以提取元素。查看coords的帮助文件,看起来返回了一个向量,所以我们可以这样做:

rocValue <- sapply(list_of_results, function(x) { x$ROCViCoorBest})

这将是一个矩阵,可能是您想要的转置。使用t 转置。

【讨论】:

  • 谢谢你,梅丽莎,这就像一个魅力!对于其他可能会阅读此内容的人,我的代码中输入=c 的行应为 ret=c
  • 我很高兴它对你有用!你能接受那种情况下的答案吗?谢谢! (我还编辑了我的答案,将input=c( 更改为ret=c(。这就是你的意思吗?
  • 是的,这就是我的意思 :) 组合数据列表有点非结构化,所以我稍微摆弄了一下以产生更有序的输出。我将在下面发布。其他人可能会做得更有说服力,但它确实有效。
【解决方案2】:

下面的脚本工作,并产生一个有序的df:

list_of_results = lapply(LETTERS[1:5], function(x) {
ROCvirus = roc(ROCTest5$Outcome,
             ROCTest5[[x]])
auc_result = auc(ROCvirus)
ROCViCoorBest = coords(ROCvirus,"best",
                     ret=c("threshold", "specificity",
                           "sensitivity", "accuracy"),
                     best.method="closest.topleft")
ROCDat = c(as.numeric(auc_result), as.numeric(ROCViCoorBest))

list(ROCDat = ROCDat)
})  
Lab = c("AUC","threshold", "specificity",
      "sensitivity", "accuracy")
OutputData=as.data.frame(list_of_results)
OutputData=cbind(Lab,OutputData)

OutputData

Lab ROCDat ROCDat.1 ROCDat.2 ROCDat.3 ROCDat.4 AUC 7.592593e-01 0.8518519 0.9074074 0.9074074 0.7962963 threshold 1.475129e+04 5395.7471701 2361.0867577 1072.7211367 361.2662753 specificity 6.666667e-01 0.7777778 0.7777778 0.7777778 0.7777778 sensitivity 6.666667e-01 0.8333333 0.8333333 1.0000000 0.8333333 accuracy 6.666667e-01 0.8000000 0.8000000 0.8666667 0.8000000

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-22
    • 1970-01-01
    • 2011-12-20
    • 2013-02-26
    • 2016-11-09
    相关资源
    最近更新 更多