在 R 中使用替换 plyr 或 dplyr 的多个条件

Multiple conditions using replace plyr or dplyr in R

这是一个数据集:

> mydat
species section obs doy ranking
   A      A1  b1 123     2.1
   A      A2  b2 135     2.2
   A      A3  b3 147     2.3
   B      A1  b2 124     2.2
   B      A2  b3 132     2.3
   B      A3  b2 145     2.2
   C      A1  b1 120     2.1
   C      A2  b3 133     2.3
   C      A3  b2 137     2.2 

我正在尝试编码;对于 obs==b2 的每个物种,如果 b2 的 doy > b3 的 doy,则排名 ==“2.4”。如果 b2 的 doy < b3 的 doy,那么排名=“2.2”(保持不变),所以我得到这个结果:

> mydat2
species section obs doy ranking
   A      A1  b1 123     2.1
   A      A2  b2 135     2.2
   A      A3  b3 147     2.3
   B      A1  b2 124     2.2
   B      A2  b3 132     2.3
   B      A3  b2 145     2.4
   C      A1  b1 120     2.1
   C      A2  b3 133     2.3
   C      A3  b2 137     2.4 

我使用包 plyr 来避免循环,因为我发现循环很难理解。我知道现在很多人使用 dplyr 而不是 plyr,所以我很高兴得到使用 plyr 或 dplyr 的答案。 这是我笨拙的尝试:

require (plyr)
mydat2 <- ddply(.data=mydat,
            .variables=c("species"),
            function(x){
              return(data.frame(replace(x$ranking, x$doy[x$obs=='b2']>x$doy[x$obs=="b3"],2.4)))})

这可行,但数据集中只剩下物种和排名。我如何正确编码以保持整个数据集的排名变化? 谢谢你的帮助。

假设每个物种只有一个 b3 的 doy 值,您可以将这些值作为单个值 table,然后将其与另一个 table 合并以简化比较,全部使用dplyr:

library(dplyr)

# get a single doy value for each species
b3values  <- mydat %>% 
  filter(obs == 'b3') %>% 
  group_by(species) %>% 
  summarize(
    # using min(doy) but if there's only one value, you could use any grouping function like sum, max, etc
    b3doy = min(doy)
  )

# join b3values to your original data
mydat2  <- mydat %>% 
  left_join(b3values, by = 'species') %>% 
  mutate(
    # use case_when() to lay out your conditions and the values you want
    ranking = case_when(
        obs == 'b2' & (doy > b3doy) ~ 2.4
      , obs == 'b2' & (doy < b3doy) ~ 2.2
        # default value is to keep the ranking as-is
      , T ~ ranking
    )
  ) %>%
 # optionally, drop the extra b3doy column
 select(-b3doy)