Home > Enterprise >  Using a data frame of replacement values to replace values in another data frame in R?
Using a data frame of replacement values to replace values in another data frame in R?

Time:09-16

I have a data frame of values:

df <- structure(list(X1 = 1:2, X2 = c(1L, 3L), X3 = 2:3), class = "data.frame", row.names = c(NA, -2L))

  X1 X2 X3
1  1  1  2
2  2  3  3

And a data frame containing replacement values:

replacement_values <- structure(list(num = c("1", "2", "3"), . = c("cat", 
"dog", "mouse")), row.names = c(NA, 
-3L), class = "data.frame")

  num     .
1   1   cat
2   2   dog
3   3 mouse

For example, every time the number "1" is found in the first data frame, I would like it replaced by the word "cat", every time "2" is found I want it replaced by "dog" and every time "3" is found I want it replaced by "mouse". So Ideally I would end up with a data frame that looks like this:

    X1    X2    X3
1  cat   cat   dog
2  dog mouse mouse

I could do it like this but it's very long winded and doesn't use the replacement_values data frame:

df <- df %>%
    dplyr::mutate(
        X1 = X1 %>% 
            gsub("1", "cat", .) %>%
            gsub("2", "dog", .) %>%
            gsub("3", "mouse", .),
        X2 = X2 %>% 
            gsub("1", "cat", .) %>%
            gsub("2", "dog", .) %>%
            gsub("3", "mouse", .),
        X3 = X3 %>% 
            gsub("1", "cat", .) %>%
            gsub("2", "dog", .) %>%
            gsub("3", "mouse", .)
            )

Is there a better way?

CodePudding user response:

You could first unlist the values in your dataframe df and match the values from replacement_values with df like this:

df[] <- replacement_values$.[match(unlist(df), replacement_values$num)]
df
#>    X1    X2    X3
#> 1 cat   cat   dog
#> 2 dog mouse mouse

Created on 2022-09-16 with reprex v2.0.2

CodePudding user response:

library(tidyverse)
replacement_values <-
  structure(list(
    num = c("1", "2", "3"),
    . = c("cat",
          "dog", "mouse")
  ),
  row.names = c(NA,-3L),
  class = "data.frame")

df <-
  structure(list(
    X1 = 1:2,
    X2 = c(1L, 3L),
    X3 = 2:3
  ),
  class = "data.frame",
  row.names = c(NA,-2L))

map_df(df, ~replacement_values$.[match(.x, table = replacement_values$num)])
#> # A tibble: 2 x 3
#>   X1    X2    X3   
#>   <chr> <chr> <chr>
#> 1 cat   cat   dog  
#> 2 dog   mouse mouse

Created on 2022-09-16 with reprex v2.0.2

CodePudding user response:

With dplyr, match is still the best option. Use across to apply the change over all functions. Note that it's preferable in this case to use function(x) instead of the usual ~ since you have . as a variable name.

df %>% 
  mutate(across(everything(), function(x) replacement_values$.[match(x, replacement_values$num)]))

output

   X1    X2    X3
1 cat   cat   dog
2 dog mouse mouse

CodePudding user response:

Below is to demonstrate that lapply can be useful.

df <- structure(list(X1 = 1:2, X2 = c(1L, 3L), X3 = 2:3), class = "data.frame", row.names = c(NA, -2L))
df[]=lapply(df, function(x) gsub(1,"cat", x))
df[]=lapply(df, function(x) gsub(2,"dog", x))
df[]=lapply(df, function(x) gsub(3,"mouse", x))

the result:

X1  X2  X3
<chr>   <chr>   <chr>
cat cat     dog
dog mouse   mouse
  • Related