Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Conditionally change values in a data frame to their column name

Tags:

r

dplyr

purrr

I have a data frame that looks like this

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))

I want to use dplyr or purrr to change the values that are equal to 1 in var1 and var2, to the name of their column and keep the 0's the way they are.

The result would look like this.

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

I have tried using dplyr::mutate_at

mutate_at(test_data,
          vars(var1, var2), 
          function(var_x) { ifelse(var_x == 1, colnames(var_x), var_x) })

This returns the following error. So, probably not the best way to go.

Error in evalq(sys.calls(), ) : replacement has length zero In addition: Warning message: In rep(yes, length.out = length(ans)) : 'x' is NULL so the result will be NULL

And I have tried using purrr:map_at

map_at(test_data, 
       c("var1", "var2"), 
       function(var_x) { ifelse(var_x == 1, colnames(var_x), var_x) })

And this returns this error.

Error in ans[test & ok] <- rep(yes, length.out = length(ans))[test & ok] : replacement has length zero In addition: Warning message: In rep(yes, length.out = length(ans)) : 'x' is NULL so the result will be NULL

While I'd prefer to work with dplyr or purrr, I'm open to suggestions using other approaches.

like image 792
Juan Bosco Avatar asked Dec 13 '22 22:12

Juan Bosco


1 Answers

Here is an idea via tidyverse. The trick here is to gather first, replace the values and then 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
like image 169
Sotos Avatar answered Jan 13 '23 12:01

Sotos