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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With