Reputation: 73
I have data in the format outlined below, where all of the variables I need to work with are either NA
or the name of the variable, and I need to change the NAs to 0 and the strings to 1. I'm trying to use dplyr::across()
and ifelse()
, but what gets returned is all 1s. The only solution I have right now that works is mutating each variable individually.
How would I change all NA
s to 0 and all strings to 1 across multiple variables at once?
library(dplyr)
color_names <- c("black", "grey", "white", "purple")
my_colors <- tribble(
~black, ~grey, ~white, ~purple,
NA, "grey", NA, "purple",
NA, NA, "white", NA,
"black",NA, NA, NA,
NA, "grey", NA, NA
)
my_colors %>%
mutate(across(all_of(color_names), ~ifelse(is.na(cur_column()), 0, 1)))
#> # A tibble: 4 x 4
#> black grey white purple
#> <dbl> <dbl> <dbl> <dbl>
#> 1 1 1 1 1
#> 2 1 1 1 1
#> 3 1 1 1 1
#> 4 1 1 1 1
Created on 2021-01-13 by the reprex package (v0.3.0)
Upvotes: 5
Views: 4733
Reputation: 1925
This also works, I think is the simplest way.
tribble(
~black, ~grey, ~white, ~purple,
NA, "grey", NA, "purple",
NA, NA, "white", NA,
"black",NA, NA, NA,
NA, "grey", NA, NA
) %>%
modify(~ ifelse(is.na(.), 0, 1))
# A tibble: 4 x 4
black grey white purple
<dbl> <dbl> <dbl> <dbl>
1 0 1 0 1
2 0 0 1 0
3 1 0 0 0
4 0 1 0 0
Upvotes: 1
Reputation: 389047
Using across
you can avoid ifelse
by doing :
library(dplyr)
my_colors %>% mutate(across(.fns = ~+(!is.na(.))))
However, you can also avoid across
since is.na
works with dataframes/tibbles.
my_colors[] <- +(!is.na(my_colors))
my_colors
#A tibble: 4 x 4
# black grey white purple
# <int> <int> <int> <int>
#1 0 1 0 1
#2 0 0 1 0
#3 1 0 0 0
#4 0 1 0 0
!is.na(.)
returns a logical vector TRUE
/FALSE
and +
is used to convert them to 1
/0
.
Upvotes: 5
Reputation: 26650
I guess you could do it like this:
library(tidyverse)
color_names <- c("black", "grey", "white", "purple")
my_colors <- tribble(
~black, ~grey, ~white, ~purple,
NA, "grey", NA, "purple",
NA, NA, "white", NA,
"black",NA, NA, NA,
NA, "grey", NA, NA
)
my_colors %>%
mutate(across(.cols = everything(),
.fns = ~ ifelse(is.na(.x) == TRUE, 0, 1)))
# A tibble: 4 x 4
black grey white purple
<dbl> <dbl> <dbl> <dbl>
1 0 1 0 1
2 0 0 1 0
3 1 0 0 0
4 0 1 0 0
Upvotes: 3
Reputation: 680
You can try this:
my_colors %>% mutate(across(everything(), ~if_else(is.na(.x), 0, 1)))
Upvotes: 0