将sum应用于按子串分组的data.frame,使用R.

时间:2012-02-23 21:51:03

标签: r

示例数据:

> mat1 = as.data.frame(matrix(c("D-J10-N1","D-J10-N2","D-J2-N1","D-J2-N2",3,6,5,7,8,4,2,3,4,1,2,3), ncol = 4));
> mat1
        V1 V2 V3 V4
1 D-J10-N1  3  8  4
2 D-J10-N2  6  4  1
3  D-J2-N1  5  2  2
4  D-J2-N2  7  3  3

期望的输出:

> results
        V1 V2 V3 V4
    1 J10  9  12  5
    2 J2   12 5   5

所以我需要通过V1的子串将V2加到V4,然后在我的结果中返回这个子串。我可以将我的组定义为:

> groups <- substr(mat1[,1],1,5)
> groups
[1] "D-J10" "D-J10" "D-J2-" "D-J2-"

我想在下面使用了rowum:

> rowsum(mat1,groups, reorder = TRUE)

但是,rowsum似乎只接受组的数值?我已经看过申请家庭功能,但没有找到运气....有关如何解决的任何想法?

非常感谢帮助!!

3 个答案:

答案 0 :(得分:2)

设置data.frame有助于使列类更适合(目前它们都是因素)。

mat1 <- data.frame(V1=c("D-J10-N1","D-J10-N2","D-J2-N1","D-J2-N2"),V2=c(3,6,5,7),V3=c(8,4,2,3),V4=c(4,1,2,3))

然后,您可以使用aggregatesub来挑选您的子字符串:

aggregate(mat1[-1],by=list(sub("D-(J[0-9]+)-[A-Z0-9]+","\\1",mat1$V1)),sum)
  Group.1 V2 V3 V4
1     J10  9 12  5
2      J2 12  5  5

答案 1 :(得分:1)

首先,让您的数据略有不同。

mat1 <- data.frame(V1 = c("D-J10-N1","D-J10-N2","D-J2-N1","D-J2-N2"),
                   V2 = c(3,6,5,7),
                   V3 = c(8,4,2,3),
                   V4 = c(4,1,2,3))

如果您查看初始数据的str,则它们都是字符。这就是为什么rowums erros。

使用strsplitlapply可以帮助您入门:

mat1$new.V1 <- unlist(lapply(strsplit(mat1$V1, '-'), '[', 2))

但是,根据第一列中的数据,您可能希望使用gsub和正则表达式:

gsub('.+-([0-z]+)-.+','\\1',mat1$V1)

或类似的......

然后我会查看plyr包。

ddply(mat1, .(new.V1), summarise, sums = sum(V2, V3, V4))

或者作为丑陋的oneliner:

ddply(mat1, .(unlist(lapply(strsplit(mat1$V1, '-'), '[', 2))), summarise, sum(V2, V3, V4))

答案 2 :(得分:0)

data.table包适用于此类聚合。正如其他人所说,我会重新格式化您的数据,如下所示:

library(data.table)
mat1 <- data.table(V1=c("D-J10-N1","D-J10-N2","D-J2-N1","D-J2-N2"),
                   V2=c(3,6,5,7),
                   V3=c(8,4,2,3),
                   V4=c(4,1,2,3),
                   key="V1")

然后你可以这样总结:

mat1[, lapply(.SD, sum), by=list(V1b=gsub(".*\\-(.*)\\-.*", "\\1", mat1[,V1]))]
#   V1b V2 V3 V4
#1: J10  9 12  5
#2:  J2 12  5  5

lapply(.SD, sum)部分对每列进行求和,by部分按您请求的子字符串对其进行分组(使用gsub和正则表达式)。