trun ifelse() function into a for loop

Hello Team,

I have a working code below, it scan all of columns (the column name start with 'data') and put the correct value into a field

try2.un$keyword2 <-
  ifelse(grepl("keyword2",try2.un$data1), try2.un$data1,
         ifelse(grepl("keyword2",try2.un$data2), try2.un$data2,
                ifelse(grepl("keyword2",try2.un$data3), try2.un$data3,
                       ifelse(grepl("keyword2",try2.un$data4), try2.un$data4,
                              ifelse(grepl("keyword2",try2.un$data5), try2.un$data5,NA
                              ) ) ) ) )

Because the columns of data1 .. 5 were created in dynamic way, so it has 5 fields this time, it maybe 15 columns next time. So, I learn from internet to write the code below:

for(i in grep("data", names(df))) {
   is.na(try2.un$keyword2) <- !grepl("keyword2", df[[i]])
}

It is no error message, but try2.un$keyword2 is NA. I guess, it use data5 field value to update keyword2 field. I know there is not 'keyword2' if data5, but it may have it in other situation. And I'm sure the column had values in old way. Could you look at it and tell me how to fix it?

Thanks,

Kai

It's hard for me to help you without a reprex, but I think you should look at some functions in the package dplyr.

Some combination of mutate(), across(), contains(), and maybe rowwise(). Functions in the stringr package contain better functions for regex matching.

If you'd like more detailed help, try attaching a reprex to this post. If you're unsure what a reprex is, this post will teach you all about them: FAQ: What's a reproducible example (`reprex`) and how do I create one?

OK, here is my full code for try

library(tidyverse)
library(stringr)

try <- data.frame(id=c(1:3),
                  testing_str=c(
                    "keyword1 xxx    xxxx keyword2 yyyyy    yyy keyword3 zzzz    zzzz",
                    "keyword2 keiwae;cse keyword1 z,.xcvweir keyword4 mrgksdfgirejk",
                    "keyword3 rtfg.,ertl keyword2 m,asdfieldf keyword4 klaksdiekasdf keyword1 .,;asdjhkasfd"))


k <- str_replace_all(try$testing_str, '(?=keyword1|keyword2|keyword3|keyword4)', "-_-") 
s <- strsplit(k, '-_-') 

try2 <- tibble(data = s) %>% 
  unnest_wider(col = data, names_sep = "") %>% 
  mutate(across(starts_with("data"), trimws)) %>% 
  rowid_to_column("id") %>%
  as.data.frame() %>%
  cbind(try) 

try2.un <- try2[!duplicated(as.list(try2))] 

try2.un$keyword2 <-
  ifelse(grepl("keyword2",try2.un$data1), try2.un$data1,
         ifelse(grepl("keyword2",try2.un$data2), try2.un$data2,
                ifelse(grepl("keyword2",try2.un$data3), try2.un$data3,
                       ifelse(grepl("keyword2",try2.un$data4), try2.un$data4,
                              ifelse(grepl("keyword2",try2.un$data5), try2.un$data5,NA
                              ) ) ) ) )

you can see try2.un$keyword2 can get values if I use ifelse(....) statement . I want to use for loop to do this which will look at all of date1 ... 5 columns. Since data1 -- 5 columns are created in dynamic way (the number of data columns will keep change), I hope use loop to avoid manual checking. So, I learn from internet to write the for loop below:

for(i in grep("data", names(df))) {
   is.na(try2.un$keyword2) <- !grepl("keyword2", df[[i]])
 }

the code can be ran, but it doesn't provide the same result. I want to learn how to fix the problem.

Thanks,

Kai

I would do it like this


try2.un |>
  rowwise() |>
  mutate(
    keyword2 = paste0(map_chr(
      c_across(starts_with("data")),
      ~ {if_else(str_detect(.x,
          pattern = fixed("keyword2")
        ), true = .x, false = "")}
    ),    collapse = "")
  ) |> ungroup()
1 Like

Hi nirgrahamuk,
It is a good solution. I don't need to review data..... filelds and then write ifelse() statement.
Thank you,
Kai

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.