有条件地将数据框中的值更改为其列名

Jua*_*sco 4 r dplyr purrr

我有一个看起来像这样的数据框

set.seed(123)
test_data <- data.frame(id   = 1:6,
                        var1 = rbinom(n = 6, size = 1, prob = .5),
                        var2 = rbinom(n = 6, size = 1, prob = .5),
                        age  = sample(18:30, size = 6, replace = T))
Run Code Online (Sandbox Code Playgroud)

我想使用dplyrpurrr更改等于1 in var1var2其列的名称的值,并按照它们的方式保持0.

结果看起来像这样.

id    var1  var2    age
1     0     var2    26
2     var1  var2    25
3     0     var2    19
4     var1  0       29
5     var1  var2    21
6     0     0       18
Run Code Online (Sandbox Code Playgroud)

我试过用 dplyr::mutate_at

mutate_at(test_data,
          vars(var1, var2), 
          function(var_x) { ifelse(var_x == 1, colnames(var_x), var_x) })
Run Code Online (Sandbox Code Playgroud)

这将返回以下错误.所以,可能不是最好的方式.

evalq中的错误(sys.calls(),):replacement的长度为零另外:警告消息:在rep(yes,length.out = length(ans))中:'x'为NULL,因此结果为NULL

我尝试过使用 purrr:map_at

map_at(test_data, 
       c("var1", "var2"), 
       function(var_x) { ifelse(var_x == 1, colnames(var_x), var_x) })
Run Code Online (Sandbox Code Playgroud)

这会返回此错误.

ans [test&ok]错误< - rep(是的,length.out = length(ans))[test&ok]:替换长度为零另外:警告消息:在rep(yes,length.out = length( ans)):'x'为NULL,因此结果为NULL

虽然我更喜欢一起工作dplyr或者purrr,我愿意用其他方法的建议.

Sot*_*tos 5

这是一个想法tidyverse.这里的诀窍是gather首先,替换值,然后spread

library(tidyverse)

test_data %>% 
  gather(var, val, -c(id, age)) %>% 
  mutate(val = ifelse(val == 1, var, val)) %>% 
  spread(var, val)

#  id age var1 var2
#1  1  26    0 var2
#2  2  25 var1 var2
#3  3  19    0 var2
#4  4  29 var1    0
#5  5  21 var1 var2
#6  6  18    0    0
Run Code Online (Sandbox Code Playgroud)