Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
405 views
in Technique[技术] by (71.8m points)

r - Recode multiple variables using across, case_when and rec (sjmisc)

I'll start with some example data:

set.seed(1)
exampledata <- data.frame(
  a = sample(1:5, 10, replace = TRUE),
  b = sample(1:5, 10, replace = TRUE),
  c = sample(1:5, 10, replace = TRUE),
  a_long = sample(1:5, 10, replace = TRUE),
  b_long = sample(1:5, 10, replace = TRUE),
  c_long = sample(1:5, 10, replace = TRUE)
)

I am trying to replace the values in columns a to c with recoded values from the corresponding _long columns, when a condition on the original column is met. This accomplishes what I want but doesn't scale well:

library(tidyverse)
library(sjmisc)

exampledata %>%
  mutate(
    a = case_when(
      a %% 2 == 1 ~ rec(a_long, rec = "1=4000; 2=12000; 3=20000; 4=30000; 5=42000"),
      TRUE ~ as.numeric(a)
    ),
    b = case_when(
      b %% 2 == 1 ~ rec(b_long, rec = "1=4000; 2=12000; 3=20000; 4=30000; 5=42000"),
      TRUE ~ as.numeric(b)
    ),
    c = case_when(
      c %% 2 == 1 ~ rec(c_long, rec = "1=4000; 2=12000; 3=20000; 4=30000; 5=42000"),
      TRUE ~ as.numeric(c)
    )
  )

Here is my attempt at doing this for all columns in one go:

exampledata %>%
  mutate(across(c(a, b, c), ~ case_when(
    .x %% 2 == 1 ~ rec(paste0(cur_column(), "_long"), rec = "1=4000; 2=12000; 3=20000; 4=30000; 5=42000"),
    TRUE ~ as.numeric(.x)
  )))

However instead of using the recoded values it puts NA's in the cells that satisfy the condition. I tried adding !! before paste0(cur_column(), "_long") but this throws an error:

Error: cur_column() must only be used inside across().

My question essentially is how to paste together the column names so that I can feed them into rec().

I would refer to keep using rec() and case_when() because my real code uses multiple conditions and has more values to recode. Any help would be much appreciated.

question from:https://stackoverflow.com/questions/65864759/recode-multiple-variables-using-across-case-when-and-rec-sjmisc

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You can use map2_dfc and pass columns in pair and apply case_when to them.

library(tidyverse)
library(sjmisc)

map2_dfc(exampledata %>% select(a:c), 
     exampledata %>% select(ends_with('long')), 
     ~case_when(.x %% 2 == 1 ~ 
                  rec(.y, rec = "1=4000; 2=12000; 3=20000; 4=30000; 5=42000"),
                TRUE ~ as.numeric(.x))) %>%
  bind_cols(exampledata %>% select(ends_with('long')))

#       a     b     c a_long b_long c_long
#   <dbl> <dbl> <dbl>  <int>  <int>  <int>
# 1 30000 20000  4000      4      3      1
# 2     4 12000     2      4      2      4
# 3 30000     2     2      4      2      5
# 4     2     2  4000      2      5      1
# 5 30000 12000     4      4      2      1
# 6  4000  4000 30000      1      1      4
# 7     2 20000     4      1      3      5
# 8 30000 20000 42000      4      3      5
# 9  4000 30000     2      1      4      4
#10 12000 20000     2      2      3      5

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...