【问题标题】:How to create summaries of subgroups based on factors in R如何根据 R 中的因素创建子组的摘要
【发布时间】:2014-06-13 05:57:45
【问题描述】:

我想计算以下示例中每个数值变量的平均值。这些需要按与“id”关联的每个因素以及与“status”关联的每个因素进行分组。

set.seed(10)
dfex <- 
data.frame(id=c("2","1","1","1","3","2","3"),status=c("hit","miss","miss","hit","miss","miss","miss"),var3=rnorm(7),var4=rnorm(7),var5=rnorm(7),var6=rnorm(7))

对于“id”组的均值,输出的第一行将标记为“mean-id-1”。标记为“mean-id-2”和“mean-id-3”的行将紧随其后。对于“状态”组的平均值,行将被标记为“平均状态未命中”和“平均状态命中”。我的目标是以编程方式生成这些均值及其行标签。

我尝试了许多不同的 apply 函数排列,但每个都有问题。我还尝试了聚合函数。

【问题讨论】:

    标签: r group-summaries


    【解决方案1】:

    可能最快的方法是使用data.table(对于大数据集),尽管我没有找到在data.table 对象中显示新行名的方法,因此我将其转换回@987654323 @

    library(data.table)
    setDT(dfex) # convert `dfex` to a `data.table` object
    #setkey(dfex, id) # This is not necessary, only if you want to sort your table by "id" column first
    dat1 <- as.data.frame(dfex[,-2, with = F][, lapply(.SD, mean), by = id])
    rownames(dat1) <- paste0("mean-id-", as.character(dat1[,"id"]))
    dat2 <- as.data.frame(dfex[,-1, with = F][, lapply(.SD, mean), by = status])
    rownames(dat2) <- paste0("mean-status-", as.character(dat2[,"status"]))
    

    【讨论】:

    • 谢谢大卫。我很难理解这是如何工作的。你能评论 '[,-2, with = F]' 和 'lapply(.SD, mean)' 吗?
    • [,-2, with = F] 只是data.table 引用列的方式,即,它的意思是“删除第二列”。 lapply(.SD, mean) 表示“在所有列上应用函数mean”。您可以使用.SDcols 手动指定要应用该函数的列。请参阅?data.table 了解更多说明。如果您有大数据集,我建议将来使用此包进行聚合
    【解决方案2】:

    使用 base R,“id”列可以使用以下内容:

    means_id <- aggregate(dfex[,grep("var",names(dfex))],list(dfex$id),mean)
    rownames(means_id) <- paste0("mean-id-",means_id$Group.1)
    means_id$Group.1 <- NULL
    

    输出:

                    var3       var4       var5       var6
    mean-id-1 -0.7182503 -0.2604572 -0.3535823 -1.3530417
    mean-id-2  0.2042702 -0.3009548  0.6121843 -1.4364211
    mean-id-3 -0.4567655  0.8716131  0.1646053 -0.6229102
    

    “状态”列也是如此:

    means_status <- aggregate(dfex[,grep("var",names(dfex))],list(dfex$status),mean)
    rownames(means_status) <- paste0("mean-status-",means_status$Group.1)
    means_status$Group.1 <- NULL
    

    【讨论】:

    • Insa,您的“聚合”解决方案似乎是最容易让我用 sd 替换 mean 的解决方案,所以我喜欢这种灵活性。我从代码的第一行中删除了 'grep("var",',因为在我的完整数据集中,列名不遵循模式。在 dfex 中,这会产生两列 - “id”和“status” -填充了 NA,但删除列很容易。谢谢!
    【解决方案3】:

    你可以这样做:

    do.call(rbind,by(dfex[,-(1:2)], paste("mean-id",dfex[,1],sep="-"), colMeans)) 
                  var3       var4       var5       var6
    mean-id-1 -0.7383944  0.5005763 -0.4777325  0.6988741
    mean-id-2 -0.0316267 -0.1764453  0.1313834  0.6867287
    mean-id-3  0.7489377  0.8091953  0.9290247 -0.1263163
    

    将两个结果创建为列表:

     lapply(c("id","status"), function(x) do.call(rbind,by(dfex[grep("var",names(dfex))], paste("mean-id",dfex[,x],sep="-"), colMeans)))
    

    更新:

    library(matrixStats)
     lapply(c("id","status"), function(x) do.call(rbind,by(dfex[grep("var",names(dfex))], paste("mean-id",dfex[,x],sep="-"), colSds)))
     [[1]]
                  var3       var4      var5      var6
     mean-id-1 0.6024318 1.36423044 0.5398717 0.7260939
     mean-id-2 0.2623706 0.08870122 0.1827246 1.0590560
     mean-id-3 1.0625137 0.16381062 1.0760977 0.3524908
    
    [[2]]
                      var3     var4      var5      var6
    mean-id-hit  0.4369311 1.036234 0.6622341 0.6506010
    mean-id-miss 0.8288436 1.035163 0.7688912 0.6799636
    

    【讨论】:

    • 很好的解决方案,谢谢。不确定这是否属于另一篇文章,但有没有办法将您的代码克隆到 calc sd?我在另一篇文章中看到 matrix.Stats 包有一个名为 colSds 的函数,但是当我运行它时,我收到以下错误消息:“UseMethod 错误(“colCounts”):没有适用于 'colCounts' 的方法应用于对象“data.frame”类的
    • 嗨'user3614783'。我无法使用相同的数据集示例重现您的错误。请检查修改后的版本。
    猜你喜欢
    • 2022-01-17
    • 2017-02-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-14
    • 2021-06-10
    相关资源
    最近更新 更多