【问题标题】:R: Mean of subsets of dataframe on both row and column labelsR:行和列标签上数据框子集的平均值
【发布时间】:2014-11-19 00:46:58
【问题描述】:

假设我有:

set.seed(42) 
d = data.frame(replicate(6,rnorm(10)))
col_labels = c("a", "a", "b", "b", "c", "c")
row_labels = c(1,1,1,2,2,3,3,4,4,4)

我现在要计算d 的子集对应col_labelsrow_labels 的每个组合的平均值,即:

s = subset(d, row_labels==1, select=col_labels=="a")
s_mean = mean(as.matrix(s))

最后,我想要一个数据框,其中行对应于row_labels,列对应于col_labels,并取子集的平均值。在没有大量 for 循环的情况下如何做到这一点?

【问题讨论】:

  • 你能告诉我们你想要的结果吗?你有三个答案,很难判断是否有任何/全部是你想要的

标签: r subset mean


【解决方案1】:

这是另一个选择:

res <- lapply(split.default(d, col_labels), FUN=by, INDICES=list(row_labels), function(x) mean(unlist(x)))
do.call(rbind, res)
#          1       2       3       4
# a  0.56201  0.1563  0.4393 -0.3193
# b -0.01075  0.7515 -0.7973 -0.8620
# c  0.28615 -0.3406  0.1443 -0.1583

【讨论】:

  • 非常感谢!这很优雅,并将数据作为矩阵返回,而不仅仅是组合列表。
【解决方案2】:

试试:

set.seed(42) 
d <- data.frame(replicate(6,rnorm(10)))
indx <- expand.grid(unique(row_labels), unique(col_labels))
val1 <- apply(indx, 1, function(x) 
         mean(as.matrix(subset(d, row_labels==x[1], select=col_labels==x[2]))))
val1
#[1]  0.56200717  0.15625521  0.43927374 -0.31929307 -0.01074557  0.75147423
#[7] -0.79730155 -0.86200887  0.28615306 -0.34058148  0.14431610 -0.15834522

或者

 fun1 <- function(x,y) mean(as.matrix(subset(d, row_labels==x, select=col_labels==y)))
 mapply(fun1, indx[,1], indx[,2])
 #[1]  0.56200717  0.15625521  0.43927374 -0.31929307 -0.01074557  0.75147423
 #[7] -0.79730155 -0.86200887  0.28615306 -0.34058148  0.14431610 -0.15834522

或使用outer

  outer(unique(row_labels), unique(col_labels), Vectorize(fun1))
  #         [,1]        [,2]       [,3]
  #[1,]  0.5620072 -0.01074557  0.2861531
  #[2,]  0.1562552  0.75147423 -0.3405815
  #[3,]  0.4392737 -0.79730155  0.1443161
  #[4,] -0.3192931 -0.86200887 -0.1583452

绑定indxval

 res <- cbind(indx, val1)
 head(res,3)
 #Var1 Var2      val1
 #1    1    a 0.5620072
 #2    2    a 0.1562552
 #3    3    a 0.4392737

 mean(as.matrix(subset(d, row_labels==1, select=col_labels=="a")))
  #[1] 0.5620072
 mean(as.matrix(subset(d, row_labels==2, select=col_labels=="a")))
 #[1] 0.1562552

更新

您也可以更改格式

 res1 <-  outer(unique(row_labels), unique(col_labels), Vectorize(fun1))
 dimnames(res1) <- list(unique(row_labels), unique(col_labels))
 res1
 #          a           b          c
 #1  0.5620072 -0.01074557  0.2861531
 #2  0.1562552  0.75147423 -0.3405815
 #3  0.4392737 -0.79730155  0.1443161
 #4 -0.3192931 -0.86200887 -0.1583452

或者你可以使用reshape2

 library(reshape2)
 acast(res, Var1~Var2, value.var="val1")
#         a           b          c
#1  0.5620072 -0.01074557  0.2861531
#2  0.1562552  0.75147423 -0.3405815
#3  0.4392737 -0.79730155  0.1443161
#4 -0.3192931 -0.86200887 -0.1583452

【讨论】:

    【解决方案3】:

    您需要将数据更改为长格式。您应该考虑为什么以这种格式导入数据,以及更好的清理方法。

    首先,设置列名

    colnames(d) <- col_labels
    

    其次,你不能有重复的行名,所以你不能简单地做行名(d)

    相反,我们将不得不以另一种方式将它们分开。你可以使用

    split(d, rowlabels)
    

    现在我们要把它变成长格式。 reshape2 包中的 melt 函数是常用的。

    require(reshape2)
    dMelt <- melt(split(d, row_labels))
    

    现在看看 dMelt。您有什么理由不能以这种方式组织数据?

    为了找到子集的手段,使用函数aggregate()

    aggregate(dMelt$value, FUN=mean, by=list(dMelt$variable, dMelt$L1))
    

    【讨论】:

      【解决方案4】:

      这里有一个使用data.table 的选项。它应该非常快并且可以使用任何循环

      library(data.table)
      library(reshape2)
      set.seed(42) 
      merge(
      setkey(data.table(variable=colnames(d),x=col_labels),variable),
      setkey(melt(setDT(d)[,row:=row_labels,],id.vars="row"),variable))[
        ,mean(value),c("row","x")]
      
         row x          V1
       1:   1 a  0.56200717
       2:   2 a  0.15625521
       3:   3 a  0.43927374
       4:   4 a -0.31929307
       5:   1 b -0.01074557
       6:   2 b  0.75147423
       7:   3 b -0.79730155
       8:   4 b -0.86200887
       9:   1 c  0.28615306
      10:   2 c -0.34058148
      11:   3 c  0.14431610
      12:   4 c -0.15834522
      

      这个想法是:

      1. 将行标签添加为一行后,将d data.frame放入长格式
      2. 将其与另一个数据表合并,以便在以前的列名和重复的列名之间建立对应关系
      3. 按行和 x 组计算平均值(合并结果)

      【讨论】:

        猜你喜欢
        • 2021-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-05
        • 2020-11-27
        • 2019-03-20
        • 2019-01-20
        • 2020-05-24
        相关资源
        最近更新 更多