0

如果我有一个数据集,如下所示:

Cohort Food1 Food2 Food 3 Food 4
--------------------------------
Group   1     1     2       3
 A      1     1     0       1
 B      0     0     1       0
 C      1     1     0       1
 D      0     0     0       1

我想总结每一行,在那里我可以将食物组定义为不同的类别。所以我想使用 Group 行作为定义向量。

这意味着食物 1 和食物 2 在第 1 组中,食物 3 在第 2 组中,食物 4 在第 3 组中。

理想的输出类似于:

Cohort Group1 Group2 Group3
 A      2       0      1
 B      0       1      0
 C      2       0      1
 D      0       0      1

我尝试使用这个基于 rowsum() 的函数但没有运气,我需要使用 ddply() 代替吗?

来自评论的示例数据:

dat <-
structure(list(species = c("group", "princeps", "bougainvillei", 
"hombroni", "lindsayi", "concretus", "galatea", "ellioti", "carolinae", 
"hydrocharis"), locust = c(1L, 0L, 0L, 1L, 0L, 0L, 0L, 0L, 0L, 
0L), grasshopper = c(1L, 0L, 0L, 1L, 0L, 0L, 1L, 0L, 1L, 0L), 
    snake = c(2L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 0L), fish = c(2L, 
    1L, 0L, 1L, 1L, 0L, 1L, 0L, 1L, 0L), frog = c(2L, 0L, 0L, 
    0L, 0L, 0L, 0L, 1L, 0L, 0L), toad = c(2L, 0L, 0L, 0L, 0L, 
    1L, 0L, 0L, 0L, 0L), fruit = c(3L, 0L, 0L, 0L, 0L, 1L, 1L, 
    0L, 0L, 0L), seed = c(3L, 0L, 0L, 0L, 0L, 1L, 0L, 0L, 0L, 
    0L)), .Names = c("species", "locust", "grasshopper", "snake", 
"fish", "frog", "toad", "fruit", "seed"), class = "data.frame", row.names = c(NA, 
-10L))
4

2 回答 2

2

很可能有更直接的方法,但您可以尝试以下方法:

  1. 首先,创建数据副本减去第二个标题行。

    dat2 <- dat[-1, ]
    
  2. melt()“reshape2”包中的等等dcast()不能很好地处理重复的列名,所以让我们让列名更“reshape2适当”。

    Seq <- ave(as.vector(unlist(dat[1, -1])), 
               as.vector(unlist(dat[1, -1])), 
               FUN = seq_along)
    names(dat2)[-1] <- paste("group", dat[1, 2:ncol(dat)], 
                             ".", Seq, sep = "")
    
  3. melt()数据集

    m.dat2 <- melt(dat2, id.vars="species")
    
  4. 使用该colsplit()函数正确拆分列。

    m.dat2 <- cbind(m.dat2[-2], 
                    colsplit(m.dat2$variable, "\\.", 
                             c("group", "time")))
    head(m.dat2)
    #         species value  group time
    # 1      princeps     0 group1    1
    # 2 bougainvillei     0 group1    1
    # 3      hombroni     1 group1    1
    # 4      lindsayi     0 group1    1
    # 5     concretus     0 group1    1
    # 6       galatea     0 group1    1
    
  5. 照常dcast()进行

    dcast(m.dat2, species ~ group, sum)
    #         species group1 group2 group3
    # 1 bougainvillei      0      0      0
    # 2     carolinae      1      1      0
    # 3     concretus      0      2      2
    # 4       ellioti      0      1      0
    # 5       galatea      1      1      1
    # 6      hombroni      2      1      0
    # 7   hydrocharis      0      0      0
    # 8      lindsayi      0      1      0
    # 9      princeps      0      1      0
    

注意:已编辑,因为原始答案不正确。

更新:基础 R 中的一种更简单的方法

如果您从转置数据开始,这个问题会更容易解决。

dat3 <- t(dat[-1, -1])
dat3 <- as.data.frame(dat3)
names(dat3) <- dat[[1]][-1]
t(do.call(rbind, lapply(split(dat3, as.numeric(dat[1, -1])), colSums)))
#               1 2 3
# princeps      0 1 0
# bougainvillei 0 0 0
# hombroni      2 1 0
# lindsayi      0 1 0
# concretus     0 2 2
# galatea       1 1 1
# ellioti       0 1 0
# carolinae     1 1 0
# hydrocharis   0 0 0
于 2012-10-08T19:11:13.233 回答
1

你可以很容易地使用基础 R 来做到这一点。这是一个例子。

首先,找出哪些动物属于哪个组:

groupings <- as.data.frame(table(as.numeric(dat[1,2:9]),names(dat)[2:9]))

attach(groupings)
grp1 <- groupings[Freq==1 & Var1==1,2]
grp2 <- groupings[Freq==1 & Var1==2,2]
grp3 <- groupings[Freq==1 & Var1==3,2]
detach(groupings)

然后,使用组rowSums()在正确的列上执行操作。

dat <- cbind(dat,rowSums(dat[as.character(grp1)]))
dat <- cbind(dat,rowSums(dat[as.character(grp2)]))
dat <- cbind(dat,rowSums(dat[as.character(grp3)]))

删除初始行和中间列:

dat <- dat[-1,-c(2:9)]

然后,只需正确重命名即可:

row.names(dat) <- rm()
names(dat) <- c("species","group_1","group_2","group_3")

你最终会得到:

      species group_1 group_2 group_3
bougainvillei       0       0       0
    carolinae       1       1       0
    concretus       0       2       2
      ellioti       0       1       0
      galatea       1       1       1
     hombroni       2       1       0
  hydrocharis       0       0       0
     lindsayi       0       1       0
     princeps       0       1       0

已编辑:将排序顺序更改为字母顺序,就像其他答案一样。

于 2012-10-08T20:12:03.310 回答