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

时间:2017-11-30 16:09:57

标签: r replace dplyr plyr

这是一个数据集:

> 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> do3 of b3,然后排名==“2.4”。如果不是b2< do3 of b3,然后排名==“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)))})

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

1 个答案:

答案 0 :(得分:1)

假设每个物种只有b3的一个值,你可以将这些值作为一个表,然后将它连接到另一个表,使你的比较简单,全部使用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)