0

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

sinderJ
  • 5
  • 3

2 Answers2

0

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     
Ronak Shah
  • 377,200
  • 20
  • 156
  • 213
  • Hey that's a nifty answer! Thank you! – sinderJ May 19 '20 at 05:33
  • By a miracle (I've been messing around with this problem on and off for longer than I'd care to admit), I got another solution this afternoon – FINALLY! Not as neat as yours @Ronak : `df$Treat1 <- NA df <- df %>% mutate(Treat1 = case_when( Pos %in% c("A") ~ "a", Pos %in% c("B") ~ "b", ))` – sinderJ May 19 '20 at 05:40
  • Then: `df[df$Pos == "AT", ] <- df[df$Pos == "AT", ] %>% group_by(Site, Pos) %>% mutate(Treat1 = ifelse((row_number() %% 2) == 1, "a", "b"))` – sinderJ May 19 '20 at 05:41
  • You can add that as an answer. – Ronak Shah May 19 '20 at 06:02
0

Another solution. Not as neat as yours Ronak:

df$Treat1 <- NA
df <- df %>% mutate(Treat1 = case_when(
  Pos %in% c("A") ~ "a", 
  Pos %in% c("B") ~ "b",
  ))     

Then:

df[df$Pos == "AT", ] <- df[df$Pos == "AT", ] %>% group_by(Site,Pos)%>% 
mutate(Treat1 = ifelse((row_number() %% 2) == 1, "a", "b"))
sinderJ
  • 5
  • 3