if else in a loop : across a sequence of values

I'm interested in replacing height values (fu_cmi) to NA if two other variables are not equal to 1, indicating height was taken on that visit (fu_cm_takeni & fu_cm_yni) . The i indicates follow up visit number and ranges from 2 to 20. The error message I receive is

' Error in for (. in i) 2:20 : 4 arguments passed to 'for' which requires 3'

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

The error is caused by the %>% on the first line that causes the first argument of for to be dataframe cleaned_data_wide_115 .
You could do something like the example below.

# define a test dataframe
cleaned_data_wide_115 <-
  data.frame(
    fu_cm_taken = rep(c(1,2,3),7),
    fu_cm_yn    = rep(c(2,1,4),7),
    fu_cm       = 1:21
  )

cleaned_data_wide_115 <- within (cleaned_data_wide_115,
{  
  for (i in 2:20) {
    if (fu_cm_taken[i]!=1 & fu_cm_yn[i]!=1) {
      fu_cm[i] = NA
    }
    else {
      fu_cm[i] = fu_cm[i] # why do you need this statement?
    }
  }
}
)

cleaned_data_wide_115$i <- NULL

print(cleaned_data_wide_115)
#>    fu_cm_taken fu_cm_yn fu_cm
#> 1            1        2     1
#> 2            2        1     2
#> 3            3        4    NA
#> 4            1        2     4
#> 5            2        1     5
#> 6            3        4    NA
#> 7            1        2     7
#> 8            2        1     8
#> 9            3        4    NA
#> 10           1        2    10
#> 11           2        1    11
#> 12           3        4    NA
#> 13           1        2    13
#> 14           2        1    14
#> 15           3        4    NA
#> 16           1        2    16
#> 17           2        1    17
#> 18           3        4    NA
#> 19           1        2    19
#> 20           2        1    20
#> 21           3        4    21
Created on 2023-08-25 with reprex v2.0.2

Thanks for this - the data is actually as such :

cleaned_data_wide_115 <-
data.frame(
fu_cm_taken1 =1,
fu_cm_yn1=NA
fu_cm1= 70,
fu_cm_taken2=0,
fu_cm_yn2=NA,
fu_cm2=0,
fu_cm_taken3=NA,
fu_cm_yn3=0,
fu_cm3=0,
)
and so on, up until fu_cm_yn20, fu_cm_taken20, and fu_cm20. I would like to replace the height to be NA if neither fu_cm_yn[i] nor fu_cm_taken[i] are 1, which indicates a height was taken on that visit.

Did you actually try to do anything with this dataset? :wink:

Taken care of the commas you could do something like

notequal <- function (x, const) {
  res <- x != const 
  res[is.na(res)] <- T
  res
}

cleaned_data_wide_115 <-
  data.frame(
    fu_cm_taken1 = c(1,2),
    fu_cm_yn1 = c(NA,2),
    fu_cm1 = c(70,2),
    fu_cm_taken2 = c(0,2),
    fu_cm_yn2 = c(8,1),
    fu_cm2 = c(0,2),
    fu_cm_taken3 = c(NA,1),
    fu_cm_yn3 = c(1,2),
    fu_cm3 = c(0,2) 
  )
print(cleaned_data_wide_115) 
#>   fu_cm_taken1 fu_cm_yn1 fu_cm1 fu_cm_taken2 fu_cm_yn2 fu_cm2 fu_cm_taken3
#> 1            1        NA     70            0         8      0           NA
#> 2            2         2      2            2         1      2            1
#>   fu_cm_yn3 fu_cm3
#> 1         1      0
#> 2         2      2

for (i in 1:3) {
  i1 <- 1 + (i-1)*3 
  i2 <- 2 + (i-1)*3 
  i3 <- 3 + (i-1)*3 
  b <-  notequal(cleaned_data_wide_115[i1],1) & 
        notequal(cleaned_data_wide_115[i2],1)
  cleaned_data_wide_115[i3][b] <- NA
}
print(cleaned_data_wide_115) 
#>   fu_cm_taken1 fu_cm_yn1 fu_cm1 fu_cm_taken2 fu_cm_yn2 fu_cm2 fu_cm_taken3
#> 1            1        NA     70            0         8     NA           NA
#> 2            2         2     NA            2         1      2            1
#>   fu_cm_yn3 fu_cm3
#> 1         1      0
#> 2         2      2
Created on 2023-08-26 with reprex v2.0.2

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.