My data look like this
Q3A1<-c(0,1,0,1,1,1,0,1,0,1)
Q3A2<-c(0,1,1,1,0,1,0,0,0,1)
Q3A3<-c(1,1,0,1,0,1,0,0,0,1)
And I would like to create a new variable Q3L were it is coded as 1 when Q1A1, Q1A2 and Q1A3 are all equal to 1
I tried this
dataQ$Q3L <- ifelse(dataQ$Q3A1==1|dataQ$Q3A2==1|dataQ$Q3A3==1, 1, 0 )
but It seemslike it is recoding as 1 if at least one of the three equal 1, but I need the tree of them to be equal to 1
I tried this as well
library(dplyr)
dataQ %>%
mutate(Q3L = case_when(Q3A1 == 1 & Q3A2 == 1 & Q3A3 == 1 ~ 1,))
not a success neither
CodePudding user response:
We can use if_all
- by looping over the columns that starts_with
'Q3A' in column names, create a logical condition to check whether the column values are 1 (.x == 1
), if_all
returns TRUE
only when all of the columns for a row are TRUE i.e. all 1, then coerce the logical (TRUE/FALSE
) to binary with
or as.integer
library(dplyr)
dataQ <- dataQ %>%
mutate(Q3L = (if_all(starts_with('Q3A'), ~ .x== 1)))
NOTE: Using |
or &
on a variable number of columns can be cumbersome, instead using either if_all
or create the logical with rowSums
data
dataQ <- data.frame(Q3A1, Q3A2, Q3A3)
CodePudding user response:
You can do this:
dataQ["Q3L"] = (dataQ$Q3A1 & dataQ$Q3A2 & dataQ$Q3A3)
Output:
Q3A1 Q3A2 Q3A3 Q3L
1 0 0 1 0
2 1 1 1 1
3 0 1 0 0
4 1 1 1 1
5 1 0 0 0
6 1 1 1 1
7 0 0 0 0
8 1 0 0 0
9 0 0 0 0
10 1 1 1 1
CodePudding user response:
Update: thanks to input from @LMc: a more generalizable way would be:
library(dplyr)
tibble(Q3A1, Q3A2, Q3A3) %>%
mutate(Q3L = ifelse(select(., contains("Q3")) %>%
rowSums() == ncol(.), 1, 0))
First answer:
We could check with rowSums
and apply an ifelse
statement:
library(dplyr)
tibble(Q3A1, Q3A2, Q3A3) %>%
mutate(Q3L = ifelse(select(., contains("Q3")) %>%
rowSums() == 3, 1, 0))
Q3A1 Q3A2 Q3A3 Q3L
<dbl> <dbl> <dbl> <dbl>
1 0 0 1 0
2 1 1 1 1
3 0 1 0 0
4 1 1 1 1
5 1 0 0 0
6 1 1 1 1
7 0 0 0 0
8 1 0 0 0
9 0 0 0 0
10 1 1 1 1
CodePudding user response:
library(dplyr)
df %>%
rowwise() %>%
mutate(Q3L = as.numeric(all(as.logical(c_across(starts_with("Q3")))))) %>%
ungroup()
Or with purrr::pmap_dbl
library(purrr)
library(dplyr)
df %>%
mutate(Q3L = pmap_dbl(across(starts_with("Q3")), ~ all(.x == 1)))
Or purrr::reduce
df %>%
mutate(Q3L = as.numeric(reduce(across(starts_with("Q3")), `&`)))
Output
Q3A1 Q3A2 Q3A3 Q3L
<dbl> <dbl> <dbl> <dbl>
1 0 0 1 0
2 1 1 1 1
3 0 1 0 0
4 1 1 1 1
5 1 0 0 0
6 1 1 1 1
7 0 0 0 0
8 1 0 0 0
9 0 0 0 0
10 1 1 1 1
How it works
Both answers work similarly. They go row-by-row and convert the rows to logical vectors. all
then tests if every element of the row-wise logical vector is TRUE
. If it is then 1
is returned otherwise 0
.
purrr::reduce
works a bit differently. For each row it reduces the row-wise vector using the &
function into a single logical value.