Reputation: 45
I have this data:
library(tidyverse)
data <- tribble(
~a, ~b , ~c , ~d,
0, 0, 0, 0,
1, 1, 0, 0,
0, 1, 0, 0,
0, 0, 0, 1
)
and would like to get this output - if there is a zero in all columns TRUE
is returned:
# A tibble: 4 x 5
a b c d new
<dbl> <dbl> <dbl> <dbl> <lgl>
1 0 0 0 0 TRUE
2 1 1 0 0 FALSE
3 0 1 0 0 FALSE
4 0 0 0 1 FALSE
I tried this and it works:
data %>%
rowwise() %>%
mutate(new = ifelse(all(c(a,b,c,d) == 0) , TRUE, FALSE))
But what if I have many more columns? I would NOT want to write something like this:
data %>%
rowwise() %>%
mutate(new = ifelse(all(c(a,b,c,d,e,f,.......z) == 0) , TRUE, FALSE))
Is there a better way of writing this?
Note: I am using dplyr 0.8.3
Upvotes: 0
Views: 377
Reputation: 269644
Here are several approaches. The first two require a recent version of dplyr, the third works with older versions of dplyr too and the fourth uses only base R.
cur_data()
refers to the current group. See https://dplyr.tidyverse.org/reference/context.html Three exclamation marks !!!
is from rlang. It is imported by dplyr and causes the columns of its argument to be passed as separate arguments to pmax
. In the last two solutions apply(data == 0, 1, all)
applies all
to each row of data == 0
.
data %>% rowwise %>% mutate(new = all(cur_data() == 0)) %>% ungroup
data %>% mutate(new = !pmax(!!!.))
data %>% mutate(new = apply(. == 0, 1, all)) # older versions of dpylr ok
transform(data, new = apply(data == 0, 1, all)) # base R
Upvotes: 1
Reputation: 160447
No need for rowwise
. Using @d.b's do.call
suggestion:
data %>%
mutate(new = do.call(pmax, .) == 0)
# # A tibble: 4 x 5
# a b c d new
# <dbl> <dbl> <dbl> <dbl> <lgl>
# 1 0 0 0 0 TRUE
# 2 1 1 0 0 FALSE
# 3 0 1 0 0 FALSE
# 4 0 0 0 1 FALSE
That works when you need all columns. If instead you need a subset, then you can use the somewhat new across
:
data %>%
mutate(new = do.call(pmax, across(a:d)) == 0)
If you don't have across
, try this base-R method for selecting a range of columns:
data %>%
mutate(new = do.call(pmax, subset(., select = a:d)) == 0)
Upvotes: 2
Reputation: 101383
One base R option is using rowSums
instead of ifelse
data$new <- rowSums(abs(data))==0
which gives
> data
# A tibble: 4 x 5
a b c d new
<dbl> <dbl> <dbl> <dbl> <lgl>
1 0 0 0 0 TRUE
2 1 1 0 0 FALSE
3 0 1 0 0 FALSE
4 0 0 0 1 FALSE
Upvotes: 2