使用嵌套 for 循环生成的唯一组合创建数据框

Create a data frame with unique combo generated from nested for loops

我有这样一个数据框:

  Feature ID Sub Value
1       A T1  B1  5.87
2       B T1  B2  3.99
3       C T1  B3 12.57
4       A T1  B2  9.22
5       B T1  B3  7.89
6       C T1  B1  4.76
7       A T2  B1  4.56
8       B T2  B2  9.26
9       C T2  B2  7.44

我想做的是 运行 这个数据集中的一个因子方差分析,因子是“子”。我想循环遍历每个功能并循环遍历每个 ID。基本上,我正在计算一个 ID 内每个特征在“Sub”之间的方差。

我已经生成了下面的代码,但它似乎不起作用。

datalist <- list()

for (i in unique(data1$Feature)) {
  for (j in unique(data1$ID)) {
    A1 <- summary(aov(data1$value ~ as.factor(data1$Sub), data=data1))
    datalist[[j]] <- A1
  }
}

big_data <- do.call(rbind, datalist)

我最终得到 big_data,这是一个包含 36 个列表的矩阵。我无法访问 Anova 输出。它不一定是数据框。即使它是循环中的“write.csv()”也会生成不同的输出。最终,我只需要 Anova 输出的“between”因子参数来生成一个图,所以如果这也可以合并到代码中,那将大有帮助。

当前设置的几个问题:

  • 您实际上并没有在 anova 调用中使用 ij,因此所有嵌套的 for 循环迭代将 return 在整个数据帧上得到完全相同的结果 运行。快速修复:subset 数据框由第 i 个和第 j 个值组成。

    anova(value ~ Sub, data = subset(data1, Feature == i & ID == j))
    
  • 您仅在 j 值下保存列表元素而不是 ij,因此迭代将重复重新分配并且仅保存 最后 j 项。快速修复:添加第 i 个和第 j 个值的命名元素。

    datalist[[paste0(i, "_", j)]] <- A1
    
  • 您正在尝试 rbind 列出对象,而不是矩阵或数据框,因为 summary.anova return 是结果列表。对于您的用例,调用 str 显示您的结果包含 1:

    的列表
    str(summary(aov(data1$value ~ as.factor(data1$Sub), data = data1)))
    List of 1
    $ :Classes ‘anova’ and 'data.frame': 2 obs. of  5 variables:
      ..$ Df     : num [1:2] ...
      ..$ Sum Sq : num [1:2] ...
      ..$ Mean Sq: num [1:2] ...
      ..$ F value: num [1:2] ...
      ..$ Pr(>F) : num [1:2] ...
    - attr(*, "class")= chr [1:2] "summary.aov" "listof"
    

    快速修复:索引第一项。

    summary(anova(...))[[1]]
    

但是,考虑 apply 家庭解决方案 bytapply 的面向对象包装器)并避免初始化列表的簿记和迭代分配在嵌套的 for 循环中。具体来说,by 可以将数据帧拆分为一个或多个组,并对子集进行 运行 操作以 return 一个列表,该列表等于组的所有可能唯一值。另外,考虑使用定义的方法来封装每个子集上的所有处理。

# USER-DEFINED METHOD
run_anova <- function(sub_df) {
  # RAW RESULTS
  anova_raw <- summary(aov(value ~ Sub, data = sub_df))[[1]]

  # CLEAN UP DATA WITH IDENTIFIERS
  anova_df <- data.frame(
    within(anova_raw, {Feature <- sub_df$Feature[1]; ID <- sub_df$ID[1]}),
    row.names = NULL,
    check.names = FALSE
  )
  
  return(anova_df)
}

datalist <- by(data1, data1[c("Feature", "ID")], run_anova)
  
big_data <- do.call(rbind, unname(datalist))