If else in a loop

I want to replace a value fu_cm[i] to be missing if a value fu_cm_taken[i] and fu_cm_yn[i] are not 1. i ranges from 1-16. I'm trying to use ifelse but getting the following.

unexpected token 'in'
unexpected token 'fu_cm_taken

length_times_renamed <- length_times_renamed %>%
  foreach(i in 1: 16) {
  if fu_cm_taken[i]!=1 & fu_cm_yn[i]!=1
    {(fu_cm[i] = .)
  else(fu_cm[i])}}

Are fu_cum, fu_cm_taken, and fu_cm_yn all columns in a data frame named length_times_renamed? If not, what is length_times_renamed? Assuming they are all column names, I would use functions from the dplyr package to do this.

library(dplyr)
length_times_renamed <- length_times_renamed |>
  mutate(fu_cm = ifelse(fu_cm_taken == 1 & fu_cm_yn ==1, fu_cm, NA))

Note that the logic is fu_cm_taken and fu_cm_yn both have to equal 1 or fu_cm is set to NA. Your code seemed to set fu_cm to an alternative value if both fu_cm_yn nad fu_cm_taken were not 1.

Among the problems with your code is that you try to pipe length_times_renamed into a loop. That is not a correct use of the pipe operator. Also, foreach is not a function I'm familiar with.

Yes, but how would I incorporate all 16 of these?

Here's a look at what I'm doing now, i[2:5]

>   lengths_times_renamed$fu_cm2 <- ifelse(lengths_times_renamed$fu_cm_taken2!=1 & lengths_times_renamed$fu_cm_yn2!=1,NA,lengths_times_renamed$fu_cm2)
>     lengths_times_renamed$fu_cm3 <- ifelse(lengths_times_renamed$fu_cm_taken3!=1 & lengths_times_renamed$fu_cm_yn3!=1,NA,lengths_times_renamed$fu_cm3)
>   lengths_times_renamed$fu_cm4 <- ifelse(lengths_times_renamed$fu_cm_taken4!=1 & lengths_times_renamed$fu_cm_yn4!=1,NA,lengths_times_renamed$fu_cm4)
>   lengths_times_renamed$fu_cm5 <- ifelse(lengths_times_renamed$fu_cm_taken5!=1 & lengths_times_renamed$fu_cm_yn5!=1,NA,lengths_times_renamed$fu_cm5)

Like many R function, ifelse() and mutate() are vectorized, they act on the whole column or vector without the need for a loop. Here is a toy example of using my code on an invented data frame.

length_times_renamed <- data.frame(fu_cm_taken = c(1,1,0,1),
                 fu_cm_yn = c(1,0,1,1),
                 fu_cm = c(4,5,6,7))
length_times_renamed
#>   fu_cm_taken fu_cm_yn fu_cm
#> 1           1        1     4
#> 2           1        0     5
#> 3           0        1     6
#> 4           1        1     7
library(dplyr)

length_times_renamed <- length_times_renamed |>
  mutate(fu_cm = ifelse(fu_cm_taken == 1 & fu_cm_yn ==1, fu_cm, NA))
length_times_renamed
#>   fu_cm_taken fu_cm_yn fu_cm
#> 1           1        1     4
#> 2           1        0    NA
#> 3           0        1    NA
#> 4           1        1     7

Created on 2023-06-09 with reprex v2.0.2

My column names are fu_cm_taken2, fu_cm_yn2, fu_cm2, fu_cm_taken3, fu_cm_yn3, fu_cm_taken3... etc.

Please upload the output of

dput(head(length_times_renamed, 10))

Okay, so basically you have a more advanced options imo. This would be to reshape your data and simplify it, to reduce the necessary code. This would involve a few steps (you could reshape you data to long, split the column names to obtain "name + number", then apply a function which applies your desired logic to each subset based on the subset).
Here is the code with a little bit of toy data and I hope I understood the data you have well enough, since you did not provide a full reprex:

set.seed(0)
Data <- data.frame(
    fu_cm_taken1 = sample(c(0,1), 50, replace = TRUE),
    fu_cm_yn1 = sample(c(0,1), 50, replace= TRUE),
    fu_cm1 = sample(c("yay", "ney"), 50, replace = TRUE),
    fu_cm_taken2 = sample(c(0,1), 50, replace = TRUE),
    fu_cm_yn2 = sample(c(0,1), 50, replace= TRUE),
    fu_cm2 = sample(c("yay", "ney"), 50, replace = TRUE)
    )

library(data.table)
Data <- as.data.table(Data)

# Reshape to long
Data  <- melt.data.table(Data, measure.vars = colnames(Data))

# Split with Regex
Data[, c("Name", "Number") := tstrsplit(variable, "(?<=[a-zA-Z])(?=[[:digit:]])", perl = TRUE)]

# Define function
myFunc <- function(dt) {
    dt[, id := 1:.N, Name]
    dt |>
        dcast.data.table(id ~ Name, value.var = "value") |>
        collapse::ftransform(
            fu_cm = fifelse(fu_cm_taken != 1 & fu_cm_yn != 1, fu_cm, NA_character_)
        ) |>
        melt.data.table(id.vars = "id") |>
        collapse::fselect(- id)
}

# Apply to each subset defined by Number
Data <- Data |>
    collapse::rsplit(~ Number) |>
    collapse::rapply2d(
        myFunc
    ) |>
    collapse::unlist2d() |>
    # this returns a data.frame, so convert back, but efficently
    collapse::qDT()

# Reshape to original form
Data[, orig_name := paste0(variable, .id)]
Data[, id := 1:.N, .(variable, .id)]
Data[, .id := NULL]
dcast.data.table(Data, id ~ orig_name, value.var = "value")

   id fu_cm1 fu_cm2 fu_cm_taken1 fu_cm_taken2 fu_cm_yn1 fu_cm_yn2
 1:  1   <NA>    ney            1            0         0         0
 2:  2   <NA>   <NA>            0            1         1         1
 3:  3   <NA>   <NA>            1            0         0         1
 4:  4   <NA>    yay            0            0         1         0
 5:  5   <NA>   <NA>            0            0         1         1
 6:  6   <NA>   <NA>            1            0         0         1
 7:  7    yay   <NA>            0            1         0         1
 8:  8   <NA>   <NA>            0            1         1         0
 9:  9   <NA>   <NA>            0            1         1         0
10: 10   <NA>   <NA>            1            1         1         1
11: 11   <NA>   <NA>            1            1         0         0
12: 12    yay    ney            0            0         0         0
13: 13   <NA>    yay            0            0         1         0
14: 14   <NA>    yay            0            0         1         0
15: 15   <NA>   <NA>            0            1         1         1
16: 16   <NA>    yay            0            0         1         0
17: 17   <NA>    ney            1            0         1         0
18: 18   <NA>   <NA>            1            1         1         0
19: 19   <NA>   <NA>            1            0         0         1
20: 20   <NA>   <NA>            1            0         1         1
21: 21   <NA>   <NA>            0            1         1         0
22: 22   <NA>   <NA>            0            0         1         1
23: 23   <NA>   <NA>            0            0         1         1
24: 24    yay   <NA>            0            1         0         1
25: 25    yay   <NA>            0            0         0         1
26: 26    ney   <NA>            0            0         0         1
27: 27   <NA>   <NA>            0            1         1         0
28: 28   <NA>   <NA>            1            1         1         0
29: 29    ney   <NA>            0            1         0         0
30: 30    ney   <NA>            0            1         0         0
31: 31   <NA>   <NA>            1            0         1         1
32: 32   <NA>   <NA>            1            1         1         0
33: 33   <NA>    ney            1            0         1         0
34: 34    ney    yay            0            0         0         0
35: 35   <NA>    ney            1            0         0         0
36: 36    ney    ney            0            0         0         0
37: 37   <NA>   <NA>            0            0         1         1
38: 38   <NA>   <NA>            1            1         0         1
39: 39   <NA>   <NA>            0            0         1         1
40: 40   <NA>   <NA>            1            1         0         1
41: 41   <NA>   <NA>            1            0         1         1
42: 42   <NA>   <NA>            1            0         0         1
43: 43   <NA>   <NA>            1            1         0         1
44: 44   <NA>    ney            0            0         1         0
45: 45   <NA>   <NA>            1            1         1         1
46: 46   <NA>   <NA>            1            1         0         0
47: 47   <NA>   <NA>            1            1         0         1
48: 48   <NA>    ney            1            0         0         0
49: 49   <NA>   <NA>            1            1         1         1
50: 50   <NA>    ney            0            0         1         0

I hope the comments explain the code well enough, if you have questions or don't think this fits your needs, just raise a question and take me. I will try to answer them.

According to the foreach command and the missing value ., I assumed that you might mix some Stata syntax here.

Based on your original code, in R it may like this:

length_times_renamed <- length_times_renamed %>%
  for (i in 1:16) {
    if (fu_cm_taken[i]!=1 & fu_cm_yn[i]!=1) {
      fu_cm[i] = NA
    }
    else {
      fu_cm[i] = fu_cm[i]
    }
  }

In this case, using ifelse is a better option.

This topic was automatically closed 21 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.