简体   繁体   中英

Multiple conditions using replace plyr or dplyr in R

Here is a dataset:

> 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 

I am trying to code; for each species where obs==b2, if doy of b2 > doy of b3, then ranking=="2.4". If doy of b2 < doy of b3, then ranking=="2.2" (remains the same), so I get this result:

> 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 

I used the package plyr to avoid loops because I find loops difficult to understand. I know a lot of people use dplyr instead of plyr nowadays, so I'd by glad for an answer using either plyr or dplyr. Here is my clumsy try:

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)))})

This works, but there is only species and ranking left in the dataset. How can I code this properly to keep the whole dataset with changes in ranking? Thank you for your help.

ASSUMING each species only ever has one doy value for b3, you could get those values as a single table, then join it to the other table to make your comparisons simple, all using 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)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM