How to group values based on NA vs. alphabet

Viewed 45

I have a column of LETTER values in alphabetic order in a dataframe partly interspersed with NA:

df1 <- data.frame(
  phase = c(NA, "A", "B", "D", NA, "A", "B", "C", "E", "A", "B", "D")
)

The LETTER values form groups: anything from A until either the next NA or the next A is a group. I'd like to create a new column to make these groups explicit.

The expected outcome is this:

df1 <- data.frame(
  phase = c(NA, "A", "B", "D", NA, "A", "B", "C", "E", "A", "B", "D"),
  group = c(NA,"group1","group1","group1",NA, "group2","group2","group2","group2","group3","group3","group3")
)

How can I create this column? I'm grateful for any advice, dplyr-based or otherwise.

What I've tried so far--with only partial success (the third group, which is not separated from the second by NA, is missed):

df1 %>% 
  mutate(group = cumsum(is.na(phase)),
         group = ifelse(is.na(phase), NA, paste("group", group, sep = "")))

   phase  group
1   <NA>   <NA>
2      A group1
3      B group1
4      D group1
5   <NA>   <NA>
6      A group2
7      B group2
8      C group2
9      E group2
10     A group2
11     B group2
12     D group2
2 Answers

If phase is "A", jump to the next group. Then replace those groups with NA when phase is NA.

library(dplyr)

df1 %>%
  mutate(group = cumsum(phase == "A" & !is.na(phase)) %>%
                 paste0("group", .) %>% 
                 replace(is.na(phase), NA))

#    phase  group
# 1   <NA>   <NA>
# 2      A group1
# 3      B group1
# 4      D group1
# 5   <NA>   <NA>
# 6      A group2
# 7      B group2
# 8      C group2
# 9      E group2
# 10     A group3
# 11     B group3
# 12     D group3

We could also do

library(dplyr)
library(stringr)
df1 %>% 
   mutate(group = str_c('group', cumsum(phase %in% 'A') * NA^is.na(phase)))
#  phase  group
#1   <NA>   <NA>
#2      A group1
#3      B group1
#4      D group1
#5   <NA>   <NA>
#6      A group2
#7      B group2
#8      C group2
#9      E group2
#10     A group3
#11     B group3
#12     D group3
Related