Search code examples
rloopsdataframedata-entry

How to iteratively populate values in a dataframe using conditional tests


I'm trying to accomplish what I initially thought would be a simple task, but my coding skills for R are apparently very rusty. Simply put, I have a data frame set up in R, "test". X1 is a factor and X2 is a column with null values:

  • X1 X2
  • F1 .
  • F1 .
  • F2 .
  • F3 .
  • F3 .

My end goal with this program is to create a function or program that will iterate over each level of the factor, ask the user for a value with which to fill X2 over the current level of X1, and then move on to the next level of X1.

How would you program this?

My issue is coming from the loop itself. Either the loop isn't rewriting the values of X2 (doing it as a local variable I assume) or I'm getting the "condition has length >1" error. Here are a few versions that I've tried:


someValue<-0
for (i in levels(test$X1)){
 if (identical(test$X1,i)) {
    test$X2<-someValue}
someValue+1
}
#This doesn't seem to overwrite X2


someValue<-0
for (i in levels(test$X1)){
 if (test$X1==i) {
    test$X2<-someValue}
someValue+1
}
#This throws the 'condition has length >1' warning. I understand why this is happening. 
However, ifelse isn't an option because I want it to do nothing 
and iterate to the next level of i if false.

I don't want to use a lookup table or a join for this process because that would eliminate the time savings I'm trying to get by writing this. But apparently I'm pretty ill-equipped to do loops in R!


Solution

  • This function does what you describe in the question:

    fillfac <- function(vec){
        fill <- character(length(vec))
    
        # " iterate over each level of the factor"
        for(i in levels(vec)){ 
            #"ask the user for a value with which to fill X2"
            # "over the current level of X1"
            print(paste("What should be the fill for", i, "?"))
            value <- scan(what = "character", n=1)
            fill[labels(vec)[vec] == i] <- value
        }   
    
        return(fill)
    }   
    
    

    Example:

    > X1 = factor(sample(1:5, size = 20, rep=T))
    > X2 <- fillfac(X1)
    [1] "What should be the fill for 1 ?"
    1: "one"
    Read 1 item
    [1] "What should be the fill for 2 ?"
    1: "two"
    Read 1 item
    [1] "What should be the fill for 3 ?"
    1: "three"
    Read 1 item
    [1] "What should be the fill for 4 ?"
    1: "four"
    Read 1 item
    [1] "What should be the fill for 5 ?"
    1: "five"
    Read 1 item
    > (df <- as.data.frame(cbind(X1,X2)))
       X1    X2
    1   1   one
    2   3 three
    3   1   one
    4   2   two
    5   5  five
    6   3 three
    7   3 three
    8   4  four
    9   2   two
    10  3 three
    11  2   two
    12  3 three
    13  4  four
    14  5  five
    15  2   two
    16  1   one
    17  2   two
    18  2   two
    19  5  five
    20  4  four