Search code examples
rfunctionfor-loopsapply

How to write a sequential for loop with conditional lookup capability


Beginner here. I am trying to write a for loop to adjust a score. The first part of the for loop creates a conditional output which should be passed to the second part of the for loop which has a lookup function.

In the first data.frame, a, there are 2 columns

  • score (participant score)
  • problem (problems with the participant score)

In the second data.frame, b, there are 5 columns

  • score (participant score)
  • q (adjusted score when problem = 1)
  • r (adjusted score when problem = 2)
  • s (adjusted score when problem = 0)
  • t (adjusted score when problem > 2)

In the first for loop, I find the index where a$score = b$score

Then in the second loop, I pass the index to another loop. Based on the value in a$problem, the loop returns the correct adjusted value in (q, r, s, t).

Here is data.frame a

id      score   problem
1       11      1
2       12      6
3       13      2
4       14      0
5       NA      NA

Here is data.frame b

score   q   r   s   t
11      12  13  11  NA
12      14  15  12  NA
13      16  20  13  NA
14      18  22  14  NA
NA      NA  NA  NA  NA

I would like the output of the function to be a new column in a, a$adjusted

Here is the function I have been trying,

adjust <- function (y, z){

# y = problem
# z = score

  for(j in z){
    index <- sapply(j, function(x) b$score %in% x)
    for (i in y){
      ifelse(i > 2, 
             z(i) <- b[index, 5],
             ifelse(i == 2, 
                    z(i) <- b[index, 3],
                    ifelse(i == 1, 
                           z(i) <- b[index, 2],
                           ifelse( i == 0, 
                           z(i) <- b[index, 4],
                           z(i) <- b[index, 5]))))
      print(z(i))
    }
  }
  }

This is still new for me. Not sure where I'm going wrong. When I assign:

a$adjusted <- adjust(a$problem, a$score)

Nothing happens

Any and all help very much appreciated here.


Solution

  • To simplify the nested ifelse statements I used the case_when function from the dplyr package. I also used the match function to simplify the inner loop (i.e. sapply)

    a<-read.table(header=TRUE, text="id      score   problem
    1       12      1
    2       11      6
    3       13      2
    4       14      0
    5       NA      NA")
    
    b<-read.table(header=TRUE, text="score   q   r   s   t
    11      12  13  11  NA
    12      14  15  12  NA
    13      16  20  13  NA
    14      18  22  14  NA
    NA      NA  NA  NA  NA")
    
    library(dplyr)
    
    #find column name associated with problem score if NA use the score column
    colname<-case_when(
        a$problem==0 ~ "s",
        a$problem==1 ~ "q",
        a$problem==2 ~ "r",
        a$problem >2 ~ "t",
        is.na(a$problem) ~"score"
    )
    
    # find the corresponding row in table b to match data frame a
    rowscore<-match(a$score, b$score)
    
    #column name and rowscore are the same length
    #loop through the column name/row name to find the adjusted score
    a$adjusted<-sapply(1:length(rowscore), function(i){b[[colname[i]]][rowscore[i]]} )