【问题标题】:Mean row by imbricated levels of factors按叠层因子水平排列的平均数
【发布时间】:2014-10-03 15:32:06
【问题描述】:

我有以下数据框:

df = data.frame(id=c("A","A","A","A","B","B","B","B","C","C","C","C","D","D","D","D"),
                sub=rep(c(1:4),4),
                acc1=runif(16,0,3),
                acc2=runif(16,0,3),
                acc3=runif(16,0,3),
                acc4=runif(16,0,3))

我想要的是获得每个 ID 的平均行数,也就是说我想通过平均每个 sub 的值来获得每个级别 A、B、C 和 D 的平均 acc1、acc2、acc3 和 acc4 (每个 id 有 4 个级别),最终会给出这样的结果(当然,NA 被我想要的方式替换):

dfavg = data.frame(id=c("A","B","C","D"),meanacc1=NA,meanacc2=NA,meanacc3=NA,meanacc4=NA)

提前致谢!

【问题讨论】:

    标签: r row mean multi-level


    【解决方案1】:

    试试:

    您可以使用任何专用包dplyrdata.table 或使用base R。因为您有很多以acc 开头的列来获取平均值,所以我选择dplyr。这里的思路是先通过idgroup变量,然后用summarise_each通过id得到每列的mean,即starts_withacc

     library(dplyr)
     df1 <- df %>% 
               group_by(id) %>% 
               summarise_each(funs(mean=mean(., na.rm=TRUE)), starts_with("acc")) %>%
               rename(meanacc1=acc1, meanacc2=acc2, meanacc3=acc3, meanacc4=acc4) #this works but it requires more typing.
    

    我会 rename 使用 paste

    # colnames(df1)[-1] <- paste0("mean", colnames(df1)[-1]) 
    

    给出结果

     #  id   meanacc1  meanacc2 meanacc3 meanacc4
     #1  A 1.7061929 2.401601 2.057538 1.643627
     #2  B 1.7172095 1.405389 2.132378 1.769410
     #3  C 1.4424233 1.737187 1.998414 1.137112
     #4  D 0.5468509 1.281781 1.790294 1.429353
    

    或使用data.table

     library(data.table)
     nm1 <- paste0("acc", 1:4) #names of columns to do the `means`
     dt1 <- setDT(df)[, lapply(.SD, mean, na.rm=TRUE), by=id, .SDcols=nm1]
    

    这里.SD 意味着Subset of Data.table.SDcols 是我们应用mean 操作的列。

     setnames(dt1, 2:5, paste0("mean", nm1)) #change the names of the concerned columns in the result
     dt1
    

    【讨论】:

    • +1,我现在才看到帖子和我脑海中的代码。太晚了。你会如何写rename() 部分?
    • @jazzurro 谢谢,昨天,当我尝试rename 时,由于某些奇怪的原因它无法正常工作。也许我做错了什么。我使用rename 更新了帖子,但在重命名多个变量时需要更多输入。我更喜欢有一些类似rename(paste0("mean", starts_with("acc")= starts_with("acc")) 的东西,尽管它不起作用
    • @jazzuro 谢谢,效果很好!抱歉回复晚了。
    【解决方案2】:

    (这必须至少被问过 20 次。)`聚合函数将相同的函数(作为第三个参数给出)应用于其第二个参数定义的组中其第一个参数的所有列:

    aggregate(df[-(1:2)], df[1],mean)
    

    如果你想在列名后面加上字母“mean”:

    names(df2) <- paste0("mean", names(df2)
    

    如果您想自动进行列选择,那么 grep 或 grepl 会起作用:

    aggregate(df[ grepl("acc", names(df) )], df[1], mean)
    

    【讨论】:

    • 当然还有formula的方法aggregate:aggregate(. ~ id, df[-2], mean)
    • 对。我一直忘记公式方法,因为它与其他具有三个参数的基本汇总函数(tapplybyave)有些不同:数据、索引、函数按顺序排列。即使明显不那么“优雅”,也更容易为我保持笔直。出于某种原因,我不会忘记 xtabs.formula 函数。
    【解决方案3】:

    以下是其他几个基本 R 选项:

    split + vapply(因为我们知道vapply 会尽可能简化为矩阵)

    t(vapply(split(df[-c(1, 2)], df[, 1]), colMeans, numeric(4L)))
    

    by(用do.call(rbind, ...) 获得最终结构)

    do.call(rbind, by(data = df[-c(1, 2)], INDICES = df[[1]], FUN = colMeans))
    

    两者都会给你这样的结果:

    #       acc1     acc2     acc3     acc4
    # A 1.337496 2.091926 1.978835 1.799669
    # B 1.287303 1.447884 1.297933 1.312325
    # C 1.870008 1.145385 1.768011 1.252027
    # D 1.682446 1.413716 1.582506 1.274925
    

    这里使用的样本数据是(set.seed,为了重现性):

    set.seed(1)
    df = data.frame(id = rep(LETTERS[1:4], 4),
                    sub = rep(c(1:4), 4),
                    acc1 = runif(16, 0, 3),
                    acc2 = runif(16, 0, 3),
                    acc3 = runif(16, 0, 3),
                    acc4 = runif(16, 0, 3))
    

    扩展到 100 万行,这两个表现都很好(虽然显然不如“dplyr”或“data.table”快)。

    【讨论】:

      【解决方案4】:

      您可以使用以下方法在基础包本身中执行此操作:

       a <- list();
      
       for (i in 1:nlevels(df$id))
       {      
          a[[i]] = colMeans(subset(df, id==levels(df$id)[i])[,c(3,4,5,6)]) ##select columns of df of which you want to compute the means. In your example, 3, 4, 5 and 6 are the columns
       }
       meanDF <- cbind(data.frame(levels(df$id)), data.frame(matrix(unlist(a), nrow=4, ncol=4,  byrow=T)))
      
      colnames(meanDF) = c("id", "meanacc1", "meanacc2", "meanacc3", "meanacc4")
      meanDF
      
      id meanacc1 meanacc2  meanacc3  meanacc4
      A 1.464635 1.645898 1.7461862 1.026917
      B 1.807555 1.097313 1.7135346 1.517892
      C 1.350708 1.922609 0.8068907 1.607274
      D 1.458911 0.726527 2.4643733 2.141865
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-07-18
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多