Merging binary variables in R to a new variable

Viewed 71

I have three categorical variables i.e. stroke, MI and BP with values of 0 = yes and 1= No. I want to merge them to make a new variable "cvd" out of these three variables where each row with 0 gets 0 values in new cardiovascular variable. For example:

Stroke  MI  BP  CVD
0       1    1   0
1       1    1   1
1       1    0   0

I tried the following code but this is not what i want

transform(koratest, cvd=paste(stroke,MI, BP))

Can someone please help what could be the script for this?

Best,

Thank you for all the solutions. What to do if there is missing values in any of the values to be merged. I want missing values to be labelled as 1 but if there is 0 with missing value, i want cvd variable to have value of 1. For example:

 Stroke  MI  BP  CVD
0       1    1   0
1       NA   NA  1
0       NA   1   0

How could i achieve such output?

8 Answers

Try,

(rowSums(df) == ncol(df)) * 1
#[1] 0 1 0

Another way:

library(dplyr)

df <- data.frame(Stroke = c(0,1,1),
                   MI = c(1,1,1),
                   BP = c(1,1,0))

df %>% 
  rowwise() %>% 
  mutate(
    CVD = min(Stroke, MI, BP) 
  ) %>% 
  ungroup()

#> # A tibble: 3 × 4
#>   Stroke    MI    BP   CVD
#>    <dbl> <dbl> <dbl> <dbl>
#> 1      0     1     1     0
#> 2      1     1     1     1
#> 3      1     1     0     0

Created on 2022-07-11 by the reprex package (v2.0.1)

Try this using dplyr rowwise function

library(dplyr)

df |> rowwise() |> mutate(CVD = if(all(c_across() == 1)) 1 else 0) |> ungroup()
  • output
# A tibble: 3 × 4
# Rowwise: 
  Stroke    MI    BP   CVD
   <int> <int> <int> <dbl>
1      0     1     1     0
2      1     1     1     1
3      1     1     0     0

Don't know how you arrange your variables. If they are separted vectors, this should work:

Stroke = c(0,1,1)
MI = c(1,1,1)
BP = c(1,1,0)
CVD = as.numeric(Stroke & MI & BP)

If a data.frame:

df$CVD = with(df, as.numeric(Stroke & MI & BP)

Or the solutions mentioned by others.

Maybe this:

library(tidyverse)

Data <- data.frame(Stroke = c(0,1,1),
                   MI = c(1,1,1),
                   BP = c(1,1,0))

Data <- Data %>% 
  mutate(CVD = if_else(Stroke == 1 &MI == 1 & BP == 1, 1, 0))

base R option:

df$CVD <- apply(df,2, function(x) !any(0 %in% x)) + 0
df

Output:

  Stroke MI BP CVD
1      0  1  1   0
2      1  1  1   1
3      1  1  0   0

Using rowSums in cbind detects that dat is a data frame and creates such.

cbind(dat, CVD=+(rowSums(dat[c('Stroke', 'MI', 'BP')]) == 3))
#   Stroke MI BP CVD
# 1      0  1  1   0
# 2      1  1  1   1
# 3      1  1  0   0

If you only have these columns, it simplifies to:

cbind(dat, CVD=+(rowSums(dat) == 3))

Data:

dat <- structure(list(Stroke = c(0L, 1L, 1L), MI = c(1L, 1L, 1L), BP = c(1L, 
1L, 0L)), class = "data.frame", row.names = c(NA, -3L))

Another way to solves your problem:

df$CVD = with(df, pmin(Stroke, MI, BP)) 

  Stroke MI BP CVD
1      0  1  1   0
2      1  1  1   1
3      1  1  0   0

# or
library(data.table)

setDT(df)[, CVD := pmin(Stroke, MI, BP)]

# or
library(dplyr)

df = df %>% 
  mutate(CVD = pmin(Stroke, MI, BP))
Related