在R中使用我自己的函数汇总数据帧中任意列

在R中使用我自己的函数汇总数据帧中任意列,r,plyr,dplyr,R,Plyr,Dplyr,我正在寻找一种方法来总结R中的一个大型平面实验结果表。总结并不简单,因为我需要总结任意列(不能预先硬编码列),并使用任意定义的总结函数 例如,假设我有下面的平面表格,my_table my_table id_1 id_2 rep_id value_1 value_2 1 a 1 1 0.0 0.0 2 a 1 2 0.2 0.2 3 a 1 3 0.3 0.3 4

我正在寻找一种方法来总结R中的一个大型平面实验结果表。总结并不简单,因为我需要总结任意列(不能预先硬编码列),并使用任意定义的总结函数

例如,假设我有下面的平面表格,
my_table

my_table
   id_1 id_2 rep_id value_1 value_2
1     a    1      1     0.0     0.0
2     a    1      2     0.2     0.2
3     a    1      3     0.3     0.3
4     a    1      4     0.4     0.4
5     a    1      5     0.1     0.1
6     a    2      1     0.5     0.0
7     a    2      2     1.5     1.5
8     a    2      3     2.5     2.5
9     a    2      4     3.5     3.5
10    a    2      5     4.5     4.5
我会将
我的_表
汇总成如下表格:

> summary_table
  id_1 id_2 value_1.min value_1.max value_1.mean_plus_sd value_2.min value_2.max value_2.mean_plus_sd
1    a    1         0.0         0.4            0.3581139           0         0.4            0.3581139
2    a    2         0.5         4.5            4.0811388           0         4.5            4.1464249
总结很复杂,因为我想:

  • 指定要分组的变量,例如
    key\u fields=c(“id\u 1”、“id\u 2”)
  • 指定要汇总的列,例如
    fields\u to\u summary=c(“value\u 1”、“value\u 2”)
  • 使用我自己的汇总函数(也命名新列)
  • 下面是我目前用来做这三件事的代码。这很好,但效率也很低。如有任何改进,我们将不胜感激:

    library(plyr)
    
    # create table
    my_table = data.frame("id_1"  = c("a","a","a","a","a","a","a","a","a","a")
                        ,"id_2" = c("1","1","1","1","1","2","2","2","2","2")
                        ,"rep_id" = c(1,2,3,4,5,1,2,3,4,5)
                        ,"value_1"= c(0.0,0.2,0.3,0.4,0.1,0.5,1.5,2.5,3.5,4.5)
                        ,"value_2"= c(0.0,0.2,0.3,0.4,0.1,0.0,1.5,2.5,3.5,4.5)
        )
    
    # specify columns to group by / summarize over
    key_fields = c("id_1","id_2")
    fields_to_summarize = c("value_1","value_2")
    
    # create summary_table
    counter = 1;
    for (fname in fields_to_summarize){
    
      summary_function = function(D) data.frame(setNames(list(min(D[[fname]]),
                                                              max(D[[fname]]),
                                                              mean(D[[fname]])+sd(D[[fname]])),
                                                         paste(fname,c("min",
                                                                       "max",
                                                                       "mean_plus_sd"),
                                                               sep=".")
      ))
    
      tmp = ddply(.data = df, 
                     .variable = key_fields,
                     function(D) summary_function(D))
    
      if (counter == 1){
        summary_table = tmp;
      } else {
        summary_table = join(x=summary_table,y=tmp,by=key_fields,type="left", match="all")
      }
      counter = counter + 1;
    }
    

    这不是最终的解决方案,但也许是dplyr的良好开端

    library(dplyr)
    
    mean_plus_sd <- function(x) mean(x) + sd(x)
    key_fields = c("id_1","id_2")
    
    my_table %>%
      group_by_(.dots = key_fields) %>%
      summarise_each_(funs(min,max,mean_plus_sd), fields_to_summarize)
    
    库(dplyr)
    平均值加上标准差%
    分组依据(.dots=关键字字段)%>%
    每个字段汇总(FUN(最小值、最大值、平均值加上标准差)、字段汇总)
    
    这里有两个可以定义的快速函数。第一种是使用基本R方法,第二种是使用可能的
    数据表方法

    My_func <- function(data, fields_to_summarize, key_fields){
                        aggregate(data[fields_to_summarize], 
                         data[key_fields], 
                         function(x) c(min = min(x), 
                                      max = max(x),
                                      mean_plus_sd = mean(x) + sd(x)))
    }
    
    My_func2 <- function(data, fields_to_summarize, key_fields){
                    as.data.table(data)[, lapply(.SD, 
                                          function(x) c(min(x), max(x), mean(x) + sd(x))), 
                    key_fields, 
                    .SDcols = fields_to_summarize][, 
                          Funs := c("min", "max", "mean_plus_sd")][]
    }
    
    测试第二个函数

    library(data.table)
    My_func2(my_table, fields_to_summarize, key_fields)
    
    #    id_1 id_2   value_1   value_2         Funs
    # 1:    a    1 0.0000000 0.0000000          min
    # 2:    a    1 0.4000000 0.4000000          max
    # 3:    a    1 0.3581139 0.3581139 mean_plus_sd
    # 4:    a    2 0.5000000 0.0000000          min
    # 5:    a    2 4.5000000 4.5000000          max
    # 6:    a    2 4.0811388 4.1464249 mean_plus_sd
    

    这是使用
    聚合
    的经典机会。请在此基础上搜索许多基本相同问题(和答案)的工作示例。@Arun,您认为使用
    数据可以很好地回答这个问题吗。table
    ?我最好的尝试是
    setDT(My_table)[,lapply(.SD,function(x)c(min(x),max(x),mean(x)+SD(x)),by=key_fields,.SDcols=fields_to_summary]
    ,但这给出了一个很长的格式,您无法分辨哪个值代表什么what@Arun,这很好,尽管它仍然缺少自动命名是的!这和我想要的非常接近。唯一的问题是,这会自动在摘要字段名后面加上下划线+函数名。有没有办法让它用“.”而不是“u”(例如,用value_1.min而不是value_1_min)?@docendodiscimus感谢您的完成@伯克。你可以把最后一个换成一个。但对我来说这似乎“肮脏”,可能有更好的解决方案
    names(my_table)快速问题:data.table解决方案比dplyr快吗?我在这些论坛上看到过好几次提到它。我不知道,你可能可以在你的数据集上进行测试。
    
    library(data.table)
    My_func2(my_table, fields_to_summarize, key_fields)
    
    #    id_1 id_2   value_1   value_2         Funs
    # 1:    a    1 0.0000000 0.0000000          min
    # 2:    a    1 0.4000000 0.4000000          max
    # 3:    a    1 0.3581139 0.3581139 mean_plus_sd
    # 4:    a    2 0.5000000 0.0000000          min
    # 5:    a    2 4.5000000 4.5000000          max
    # 6:    a    2 4.0811388 4.1464249 mean_plus_sd