R colSums按组

时间:2012-01-31 17:51:52

标签: r plyr

在以下矩阵数据集中:

       1  2   3   4   5  
1950   7 20  21  15  61  
1951   2 10   6  26  57  
1952  12 27  43  37  34  
1953  14 16  40  47  94  
1954   2 17  62 113 101  
1955   3  4  43  99 148  
1956   2 47  31  85  79  
1957  17  5  38 216 228  
1958  11 20  15  76  68  
1959  16 20  43  30 226  
1960   9 28  28  70 201  
1961   1 31 124  74 137  
1962  12 25  37  41 200  

我一直试图按十年计算colSums,即从1950-1959然后从1960-69找到每一列的总和,依此类推。

我尝试了tapply,ddply等,但无法找出实际可行的东西。

4 个答案:

答案 0 :(得分:13)

首先我们设置用作输入的矩阵。

Lines <- "1  2   3   4   5  
1950   7 20  21  15  61  
1951   2 10   6  26  57  
1952  12 27  43  37  34  
1953  14 16  40  47  94  
1954   2 17  62 113 101  
1955   3  4  43  99 148  
1956   2 47  31  85  79  
1957  17  5  38 216 228  
1958  11 20  15  76  68  
1959  16 20  43  30 226  
1960   9 28  28  70 201  
1961   1 31 124  74 137  
1962  12 25  37  41 200  "
DF <- read.table(text = Lines, check.names = FALSE)
m <- as.matrix(DF)

现在,下面,我们将展示一些替代解决方案。 (1)似乎最灵活的是我们可以轻松地用其他函数替换sum以获得不同的效果,但(2)是这个特定问题的最短。另请注意,存在一些细微差别。 (1)产生一个data.frame,而另外两个产生一个矩阵。

1)aggregate

decade <- 10 * as.numeric(rownames(m)) %/% 10
m.ag <- aggregate(m, data.frame(decade), sum)

给出了这个data.frame:

> m.ag
  decade  1   2   3   4    5
1   1950 86 186 342 744 1096
2   1960 22  84 189 185  538

2)rowsum 这个更短。它产生矩阵结果。

rowsum(m, decade)

3)split/sapply 。这个也产生一个矩阵。如果我们有DF,我们可以用DF替换as.data.frame(m),稍微缩短它。

t(sapply(split(as.data.frame(m), decade), colSums))

编辑:添加解决方案(2)和(3)添加了一些说明。

答案 1 :(得分:6)

首先需要定义分组变量,然后您可以使用您选择的工具(aggregateddply,无论如何)。

> aggregate(x, by=list(trunc(as.numeric(rownames(x))/10)), sum)
  Group.1 X1  X2  X3  X4   X5
1     195 86 186 342 744 1096
2     196 22  84 189 185  538

答案 2 :(得分:3)

可能有一个更优雅的基础R解决方案,但这可行。

# Construct a nicely named vector with which to split your data.frame
breaks <- seq(1950, 2000, by=10)
names <- c("50's", "60's", "70's", "80's", "90's")
decade <- cut(as.numeric(row.names(df)), 
              seq(1950, 2000, by=10), labels=names, right=FALSE)

# by() splits df apart, operating on each of its pieces.
# do.call(rbind, ...) sutures the results back together.
do.call(rbind, by(df, decade, colSums))
#      X1  X2  X3  X4   X5
# 50's 86 186 342 744 1096
# 60's 22  84 189 185  538

答案 3 :(得分:2)

by是一个选项:

by(x,10*(as.numeric(rownames(x))%/%10),colSums)
INDICES: 1950
   1    2    3    4    5 
  86  186  342  744 1096 
------------------------------------------------------------ 
INDICES: 1960
  1   2   3   4   5 
 22  84 189 185 538