Home > Mobile >  Inserting new values into a data frame using mutate and case_when in dplyr
Inserting new values into a data frame using mutate and case_when in dplyr

Time:04-27

I have the following data frame of letters with some blank (NA) slots for the lower cases

letters_df <- data.frame(caps = LETTERS[1:10], lows = letters[c(1,2,11,11,11,11,11,11,11,10)])
letters_df[letters_df == "k"] <- NA
letters_df

To fill in some of the blanks I am using this new data frame I constructed

new_letters <- data.frame(caps = c("C", "D", "F", "G", "H"),
                     lows = c("c", "d", "f", "g", "h"))

Following on from a previous question I am using dplyr mutate and case_when as follows

letters_df %>%
  mutate(lows = case_when(
    caps %in% new_letters$caps ~ new_letters$lows,
    TRUE ~ lows))

However, the result does not add in the missing letters and throws an error asking for a vector of the same length as the letters_df column. I thought I had a good handle on the syntax here. Can help me with where I am going wrong?

CodePudding user response:

This is a typical case that rows_* from dplyr can treat:

library(dplyr)

letters_df %>%
  rows_patch(new_letters, by = "caps")

   caps lows
1     A    a
2     B    b
3     C    c
4     D    d
5     E <NA>
6     F    f
7     G    g
8     H    h
9     I <NA>
10    J    j

CodePudding user response:

You could consider using a left_join combined with coalesce:

library(dplyr)

letters_df %>% 
  left_join(new_letters, by = "caps") %>% 
  mutate(lows = coalesce(lows.x, lows.y), .keep = "unused")

This returns

   caps lows
1     A    a
2     B    b
3     C    c
4     D    d
5     E <NA>
6     F    f
7     G    g
8     H    h
9     I <NA>
10    J    j

As an alternative that is more similar to your approach, you could transform your new_letters data.frame into a lookup vector returning the same result:

lookup <- tibble::deframe(new_letters)

letters_df %>% 
  mutate(lows = case_when(caps %in% names(lookup) ~ lookup[caps],
                          TRUE ~ lows))
  • Related