Home > Software design >  Add a column with single value per group
Add a column with single value per group

Time:06-17

i have a grouped tibble with several columns. i now want to add a new column that has the same value for every row within a group but a different value for each group, basically giving the groups names. these per group values are supplied from a vector. ideally i want to do this in generic way, so it works in a function based on the number of groups the input has.

any help would be much appreciated, here is a very basic and reduced example of the tibble and vector. (the original tibble has character, int, and dbl columns)

df <- tibble(a = c(1,2,3,1,3,2)) %>% group_by(a)
names <- c("owl", "newt", "zag")
desired_output <– tibble(a = c(1, 2, 3, 1, 3, 2),
                         name = c("owl", "newt", "zag", "owl", "zag", "newt"))

as the output i would like to have the same tibble just with another column for all in group 1 = owl, 2 = newt, and 3 = zag

CodePudding user response:

Something like this?

library(dplyr)

names = c("owl", "newt", "zag") 

df %>% 
  group_by(a) %>% 
  mutate(new_col = case_when(a == 1 ~ names[1],
                       a == 2 ~ names[2],
                       a == 3 ~ names[3]))
  
       a new_col
   <dbl> <chr>  
 1     1 owl    
 2     2 newt   
 3     3 zag    
 4     1 owl    
 5     2 newt   
 6     3 zag    
 7     2 newt   
 8     3 zag    
 9     1 owl    
10     2 newt   
11     1 owl    
12     3 zag    
13     2 newt   
14     3 zag   

data:

df <- structure(list(a = c(1, 2, 3, 1, 2, 3, 2, 3, 1, 2, 1, 3, 2, 3
)), class = c("tbl_df", "tbl", "data.frame"), row.names = c(NA, 
-14L))

CodePudding user response:

Just take a as indices:

library(dplyr)

df %>%
  mutate(name = names[a])

# # A tibble: 6 × 2
#       a name
#   <dbl> <chr>
# 1     1 owl  
# 2     2 newt
# 3     3 zag
# 4     1 owl
# 5     3 zag
# 6     2 newt

You can also use recode() if a cannot be used as indices.

df %>%
  mutate(name = recode(a, !!!setNames(names, 1:3)))

Data
df <- tibble(a = c(1,2,3,1,3,2))
names <- c("owl", "newt", "zag")

CodePudding user response:

You could use factor()with mutate()

names = c("owl", "newt", "zag")
dat = data.frame(a = c(1,2,3,1,2,3,2,3,1,2,1,3,2,3))
dat %>% mutate(label = factor(a, levels = c(1,2,3), labels = names))

Just make sure the order in levels corresponds to the order in labels (i.e 1 = "owl")

  • Related