Search code examples
rloopsif-statementdplyrlevels

Assign values from one column to another based on levels of other factor: R


I want to:

  1. group by a factor (Site, Pos);
  2. if factor 'Pos' == "A", assign chosen value ("a") to the same rows in new column ('Treat1');
  3. if factor 'Pos' == "B", assign chosen value ("b") to the same rows in new column ('Treat1');
  4. if factor 'Pos' == "AT", assign one value ("a") to every first row of new column ('Treat 1') where 'Pos' == A, and second value ("b") to every second row of the same.

So far I only know how to code the first 3 points, but this loop is still not performing as I would expect. It only fills the last row in the new column Treat1. Any ideas?

Very open to different methods of approaching this, but please bear in mind that I am an R beginner.

Repro:

yow <- c(1:6) 
Pos <- c("A", "B", "A", "AT", "AT", "B")
df <- as.data.frame(Pos, yow)
df$Site <-  c("low", "low", "high", "high", "high", "high")

df$Treat1 <- NA

for (i in nrow(df %>% group_by(Site)){  
  if(df$Pos[i] == "A"){
    df$Treat1[i] <- "a"
  }
  else {
    if(df$Pos[i] == "B"){
      df$Treat1[i] <- "b"
    }
  }
}

I expect/am looking for:

  • Site Pos Treat1
  • low A a
  • low B b
  • high A a
  • high AT a
  • high AT b
  • high B b

This answer is cool, and does the first 3 steps my ifelse loop is failing at, but it doesn't speak to the 4th problem! R Create new column of values based on the factor levels of another column


Solution

  • You could use case_when in dplyr :

    library(dplyr)
    
    df %>%
      group_by(Pos) %>%
      mutate(Treat1 = case_when(Pos %in% c('A', 'B') ~ tolower(Pos), 
                                 Pos == 'AT' ~ c('a', 'b')))
    
    
    #  Pos     yow Site  Treat1
    #  <chr> <int> <chr> <chr> 
    #1 A         1 low   a     
    #2 B         2 low   b     
    #3 A         3 high  a     
    #4 AT        4 high  a     
    #5 AT        5 high  b     
    #6 B         6 high  b