Roq
Roq

Reputation: 182

replace value if a dataframe column exists in specific vector and under condition in R

I would like to replace value of df1 by two vector(g1.vec. g2.vec) and column group.

If column of df1 exitst g1.vec and group == 1, replace value to Y. If column of df1 exitst g2.vec and group == 2, replace value to X. Here is a part of example:

> df1
       ID  group    col1 col2  ...... col154
1  AMM115      2       C    A  ......     A+
2  ADM107      1      NA   NA  ......      B
3  AGM041      2       B    C  ......     C+
4  AGM132      1       A   NA  ......     A+
5  AQM007      1      NA    A  ......     B+
6  ARM028      2      NA   B+  ......     A-
7  ASM019      1       A   A+  ......     NA
8  AHM172     NA       A   A+  ......     NA
> vec
g1.vec <- c("col1", "col3", "col18", "col20", "col28", "col75", "col77", "col86", "col111")
g2.vec <- c("col2", "col13", "col37", "co38", "co44", "co87", "col123", "col41", "col154")

the output would look like:

> df2
       ID  group    col1 col2  ...... col154
1  AMM115      2       C    X  ......      X
2  ADM107      1       Y   NA  ......      B
3  AGM041      2       B    X  ......      X
4  AGM132      1       Y   NA  ......     A+
5  AQM007      1       Y    A  ......     B+
6  ARM028      2      NA    X  ......      X
7  ASM019      1       Y   A+  ......     NA
8  AHM172     NA       A   A+  ......     NA

What I have tried mutate with ifelse but I do not know how to mutate multiples column once or whatever to complete this.


Data

df1 <- structure(list(ID = c("AMM115", "ADM107", "AGM041", "AGM132",
"AQM007", "ARM028", "ASM019", "AHM172"), group = c(2L, 1L, 2L,
1L, 1L, 2L, 1L, NA), col1 = c("C", NA, "B", "A", NA, NA, "A",
"A"), col2 = c("A", NA, "C", NA, "A", "B+", "A+", "A+"), col154 = c("A+",
"B", "C+", "A+", "B+", "A-", NA, NA)), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8"))

Upvotes: 1

Views: 96

Answers (3)

akrun
akrun

Reputation: 887951

Using across and case_match from dplyr

library(dplyr)# version 1.1.0
df1 %>%
   mutate(across(any_of(g1.vec),~ case_match(group, 1 ~ 'Y', .default = .x)),
        across(any_of(g2.vec), ~ case_match(group, 2 ~ 'X', .default = .x)))

-output

      ID group col1 col2 col154
1 AMM115     2    C    X      X
2 ADM107     1    Y <NA>      B
3 AGM041     2    B    X      X
4 AGM132     1    Y <NA>     A+
5 AQM007     1    Y    A     B+
6 ARM028     2 <NA>    X      X
7 ASM019     1    Y   A+   <NA>
8 AHM172    NA    A   A+   <NA>

Upvotes: 2

Kra.P
Kra.P

Reputation: 15153

You may try

library(dplyr)
    
df1 %>%
  mutate_at(g1.vec, list(~ifelse(group == 1 & !is.na(group), 'Y', .))) %>%
  mutate_at(g2.vec, list(~ifelse(group == 2 & !is.na(group), 'X', .)))

Upvotes: 2

Ronak Shah
Ronak Shah

Reputation: 389325

Base R solution -

df[df$group %in% 1, g1.vec] <- 'Y'
df[df$group %in% 2, g2.vec] <- 'X'
df

#      ID group col1 col2 col154
#1 AMM115     2    C    X      X
#2 ADM107     1    Y <NA>      B
#3 AGM041     2    B    X      X
#4 AGM132     1    Y <NA>     A+
#5 AQM007     1    Y    A     B+
#6 ARM028     2 <NA>    X      X
#7 ASM019     1    Y   A+   <NA>
#8 AHM172    NA    A   A+   <NA>

I have used %in% instead of == here to handle the NA values.

Upvotes: 3

Related Questions