在数据框

时间:2017-03-08 13:07:36

标签: r function for-loop

我希望有一个通用函数,可以使用以下示例数据对数据框中的数据执行多个t.tests:

dat <- data.frame(ID=c(1:100),
                  DRUG= rep(c("D1","D2","D2","D3","D3","D3","D5","D1","D4","D2"),10),
                  ADR=rep(c("A1","A2","A3","A6","A7","A8","A4","A2","A1","A2"),10),
                  X= sample(1:250, 100, replace=F))

基本上,我想为DRUG-ADR的每个唯一组合运行两个t.tests,用于X的值。如果我以D1-A1为例,我想测试D1-A1与D1-A&lt; 1的X值和D1-A1与D&lt; 1-A1的X值。下面是我这个例子的语法,但我的问题是如何制作一个通用的循环/函数来为DRUG-ADR的每个独特组合执行两个测试。

x <- ifelse (dat$DRUG == "D1" & dat$ADR == "A1",dat$X, NA)
x <- x[!is.na(x)]

y <- ifelse (dat$DRUG != "D1" & dat$ADR == "A1",dat$X, NA)
y <- y[!is.na(y)]

z <- ifelse (dat$DRUG == "D1" & dat$ADR != "A1",dat$X, NA)
z <- z[!is.na(z)]

t.test(x,y)
t.test(x,z)

因此,对于记录号4(D3-A6),语法将是:

x <- ifelse (dat$DRUG == "D3" & dat$ADR == "A6",dat$X, NA)
x <- x[!is.na(x)]

y <- ifelse (dat$DRUG != "D3" & dat$ADR == "A6",dat$X, NA)
y <- y[!is.na(y)]

z <- ifelse (dat$DRUG == "D3" & dat$ADR != "A6",dat$X, NA)
z <- z[!is.na(z)]

t.test(x,y)
t.test(x,z)

任何人对一般功能都有好主意吗?

编辑:我理想的结果如下表所示:

  Drug ADR pvalue1 pvalue2
1   D1  A1  pval11  pval21
2   D2  A2  pval12  pval22
3  D.. A.. pval1.. pval2..

1 个答案:

答案 0 :(得分:1)

与每个编程问题一样,解决方案分为两个步骤:

  1. 摘要你的逻辑使其成为通用
  2. 将抽象解决方案封装到可重用的函数中
  3. 你可以继续

    1. 对所有数据重复调用该函数。
    2. 然而,首先:由于数据不足,t检验有时会失败;所以让我们替换t.test来电:

      t_test = function (x, y, ...) {
          tryCatch(t.test(x, y, ...)$p.value, error = function (err) NA)
      }
      

      然后,所有这些都在一起,这给了我们:

      library(dplyr) # Makes data manipulation easier.
      
      test_combination = function (data, id) {
          drug = data[id, ]$DRUG
          adr = data[id, ]$ADR
      
          match = filter(data, DRUG == drug, ADR == adr)$X
          mismatch1 = filter(data, DRUG != drug, ADR == adr)$X
          mismatch2 = filter(data, DRUG == drug, ADR != adr)$X
      
          list(pval1 = t_test(match, mismatch1), pval2 = t_test(match, mismatch2))
      }
      

      哪种测试单一组合。现在我们测试所有这些:

      result = lapply(dat$ID, test_combination, data = dat) %>%
          bind_rows() %>%
          bind_cols(dat, .) %>%
          select(-X)
      

      或者,使用更像dplyr(但在我看来有点模糊)的方法:

      result = dat %>%
          rowwise() %>%
          do(bind_rows(test_combination(dat, .$ID))) %>%
          bind_cols(dat, .) %>%
          select(-X)
      

      请注意此代码如何不使用显式for循环。这是您在R中处理数据的方式:将函数应用于表或列表中的项目,而不是手动迭代。

      请注意,从统计学角度来看,上述内容非常值得怀疑。至少你需要执行严格的multiple testing correction