使用管道中的标识符列创建具有最大值的新列

Create a new column with max values using the identifier column within a pipeline

我正在尝试清理一些旧代码并将其转换为“整洁”。我正在尝试在管道内创建一个新的数据列,该列是单个鱼的最大年龄。让我们将感兴趣的列表示为:

fish_1 <- data.frame(year = c(2012,2012,2015,2015,2015,2013,2013,2013,2013,2012,2012,2015,2015,2015),
                     fishid = c('a','a','b','b','b','c','c','c','c','d','d','e','e','e'), # unique identifier for each fish
                     agei = c(1,2,1,2,3,1,2,3,4,1,2,1,2,3))

# which looks like this:
fish_1
   year fishid agei
1  2012      a    1
2  2012      a    2
3  2015      b    1
4  2015      b    2
5  2015      b    3
6  2013      c    1
7  2013      c    2
8  2013      c    3
9  2013      c    4
10 2012      d    1
11 2012      d    2
12 2015      e    1
13 2015      e    2
14 2015      e    3

我想做的是创建一个新列agec,这是重复每条鱼的最大年龄,但是需要多次才能填充每条鱼的行。

所需的输出将是:

fish_2 <- data.frame(year = c(2012,2012,2015,2015,2015,2013,2013,2013,2013,2012,2012,2015,2015,2015),
                     fishid = c('a','a','b','b','b','c','c','c','c','d','d','e','e','e'), # unique identifier for each fish
                     agei = c(1,2,1,2,3,1,2,3,4,1,2,1,2,3),
                     agec = c(2,2,3,3,3,4,4,4,4,2,2,3,3,3))
# Which looks like:
fish_2

   year fishid agei agec
1  2012      a    1    2
2  2012      a    2    2
3  2015      b    1    3
4  2015      b    2    3
5  2015      b    3    3
6  2013      c    1    4
7  2013      c    2    4
8  2013      c    3    4
9  2013      c    4    4
10 2012      d    1    2
11 2012      d    2    2
12 2015      e    1    3
13 2015      e    2    3
14 2015      e    3    3

我过去这样做的方法是使用 plyr::ddply() 调用来创建一个新的数据框,然后像这样与 fish 合并:

caps = plyr::ddply(fish_1, c('fishid'), plyr::summarize, agec=max(agei))
fish = merge(fish_1, caps, by='fishid')
fish

   fishid year agei agec
1       a 2012    1    2
2       a 2012    2    2
3       b 2015    1    3
4       b 2015    2    3
5       b 2015    3    3
6       c 2013    1    4
7       c 2013    2    4
8       c 2013    3    4
9       c 2013    4    4
10      d 2012    1    2
11      d 2012    2    2
12      e 2015    1    3
13      e 2015    2    3
14      e 2015    3    3

我希望有人能帮助我在管道中简洁地实现这个数据结构。我发现的所有类似问题都非常冗长,并不针对这个问题。我是使用 tidyverse 的新手,但我无法在管道中获取 group_by() 函数(以替换 ddply() 调用),我希望有更简单的方法。

更新

对于那些感兴趣的人来说,下面的两个答案似乎都是正确的。我挣扎的原因是因为我已经在我的管道中完成了其他数据操作,并且我试图在之前对 dplyr::mutate() 的调用中完成 agec 列的形成。您可以参考我对@Thomas 回答的评论,以查看我的方式中的错误。希望这会有所帮助。

尝试 dplyr 而不是 plyr

library(dplyr)

fish_1 %>% 
  group_by(fishid) %>% 
  mutate(agec = max(agei)) 

您可以使用 dplyr 中的 group_by 对您的鱼 ID 进行分组,然后使用 max 简单地调用 mutate(还有 dplyr):

fish_1 <- data.frame(year = c(2012,2012,2015,2015,2015,2013,2013,2013,2013,2012,2012,2015,2015,2015),
                     fishid = c('a','a','b','b','b','c','c','c','c','d','d','e','e','e'), # unique identifier for each fish
                     agei = c(1,2,1,2,3,1,2,3,4,1,2,1,2,3))
fish_1 %>% 
  group_by(fishid) %>% 
  mutate(agec = max(agei))
# A tibble: 14 x 4
# Groups:   fishid [5]
    year fishid  agei  agec
   <dbl> <chr>  <dbl> <dbl>
 1  2012 a          1     2
 2  2012 a          2     2
 3  2015 b          1     3
 4  2015 b          2     3
 5  2015 b          3     3
 6  2013 c          1     4
 7  2013 c          2     4
 8  2013 c          3     4
 9  2013 c          4     4
10  2012 d          1     2
11  2012 d          2     2
12  2015 e          1     3
13  2015 e          2     3
14  2015 e          3     3

选项data.table

library(data.table)   
setDT(fish_1)[, agec := max(agei, na.rm = TRUE), fishid]