在df中添加行到组

时间:2014-05-05 12:20:45

标签: r dataframe rbind rep

我有一个data.frame,每人的行数不同。如果一个人少于4行,我想给他们4行。我希望额外的行是每个人最后一行的复制品,例如下面的Tom。

我知道如何使用此代码重复行:

dff <- df[rep(1:nrow(df), each=4), ] 

但问题在于,我没有争论只复制少于4次的ID的行。

我试过这个:

dff <- ifelse(length(df$noms < 4), 
              df[rep(1:nrow(df), each=4), ], df) ##doesn't work

我想我可以使用do.call(rbind, ...)但是我再也无法将我的论点集成到代码中。

以下是我尝试的内容:

df <- ifelse(length(df$noms<4), 
             do.call(rbind, by(df, df$noms, rbind, 1:nrow(df))), 
             df) ## doesn't work

而且我还没有设法说明要做多少次重复。

   noms fruits apple orange kiwi all_comb comb
1  mary  apple     1      0    0        1    1
2  mary  grape     0      0    0        0    1
3  mary orange     0      1    0        0    1
4  mary  apple     1      0    0        1    1
5  john banana     0      0    0        0    1
6  john  apple     1      0    0        1    1
7  john  apple     1      0    0        1    1
8  john  apple     1      0    0        1    1
9  lucy   kiwi     0      0    1        0    1
10 lucy orange     0      1    0        0    1
11 lucy  apple     1      0    0        1    1
12 lucy  berry     0      0    0        0    1
13  tom orange     0      1    0        0    1

所需的输出

   noms fruits apple orange kiwi all_comb comb
1  mary  apple     1      0    0        1    1
2  mary  grape     0      0    0        0    1
3  mary orange     0      1    0        0    1
4  mary  apple     1      0    0        1    1
5  john banana     0      0    0        0    1
6  john  apple     1      0    0        1    1
7  john  apple     1      0    0        1    1
8  john  apple     1      0    0        1    1
9  lucy   kiwi     0      0    1        0    1
10 lucy orange     0      1    0        0    1
11 lucy  apple     1      0    0        1    1
12 lucy  berry     0      0    0        0    1
13  tom orange     0      1    0        0    1
14  tom orange     0      1    0        0    1
15  tom orange     0      1    0        0    1
16  tom orange     0      1    0        0    1

以下是一些可重现的数据:

noms <- as.character(c('mary', 'mary','mary','mary','john','john','john',
                       'john','lucy','lucy','lucy','lucy', 'tom'))
fruits <- as.character(c('apple','grape','orange','apple','banana',
                         'apple','apple','apple','kiwi','orange',
                         'apple','berry', 'orange'))
df <- data.frame(noms,fruits)

2 个答案:

答案 0 :(得分:1)

您使用ifelse走在正确的轨道上。请尝试以下方法:

noms <- as.character(c('mary', 'mary','mary','mary','john','john','john',
                       'john','lucy','lucy','lucy','lucy', 'tom'))
fruits <- as.character(c('apple','grape','orange','apple','banana',
                         'apple','apple','apple','kiwi','orange',
                         'apple','berry', 'orange'))
df <- data.frame(noms,fruits)

x <- with(df, ave(rep(1, nrow(df)), noms, FUN = length))
df[rep(rownames(df), ifelse(x >= 4, 1, 4)), ]
#      noms fruits
# 1    mary  apple
# 2    mary  grape
# 3    mary orange
# 4    mary  apple
# 5    john banana
# 6    john  apple
# 7    john  apple
# 8    john  apple
# 9    lucy   kiwi
# 10   lucy orange
# 11   lucy  apple
# 12   lucy  berry
# 13    tom orange
# 13.1  tom orange
# 13.2  tom orange
# 13.3  tom orange

答案 1 :(得分:0)

使用上一个问题的代码; ddply to split and add rows to each group

这是答案

首先,在df中创建一个名为numbers的变量

df$numbers<-ave(df$noms,df$noms, FUN=seq_along)

然后操纵上一个答案中给出的代码:

AddRows <- function(df) {
  new_numbers <- seq(from = min(df$numbers), to = 4)
  new_numbers <- new_numbers[new_numbers != 0]    ##probably don't need this line
  noms <- rep(unique(df$noms), length(new_numbers))

  return(data.frame(df, new_numbers))
}

ddply(df, .(noms), AddRows)