Nick Knauer
Nick Knauer

Reputation: 4243

While Loop in R with For-Loop Inside

I have a dataframe like below:

Col1     Col2 
   1        5
   2        6
   3        6

I want to write a while loop that will find the minimum sum, add 1 for that row in a new column until that new column sum is 5. Every time a row has a min, add 1.

For example:

Col1     Col2    Col1&Col2_sum     New_Value
   1        5                6             1
   2        6                8             0 
   3        6                9             0

Now add 5 to column to col1 for the first row since 6 was the minimum.

Col1     Col2    Col1&Col2_sum     New_Value
   6        5               11             1
   2        6                8             1 
   3        6                9             0

Now Add 5 to the 2nd since 8 was the minimum.

Col1     Col2    Col1&Col2_sum     New_Value
   6        5               11             1
   7        6               13             1 
   3        6                9             1

Now Add 5 to the 3rd since 9 was the minimum.

Col1     Col2    Col1&Col2_sum     New_Value
   6        5               11             2
   7        6               13             1 
   8        6               14             1

Now Add 5 to the 1st since 11 was the minimum. (Final output)

Col1     Col2    Col1&Col2_sum     New_Value
  11        5               16             2
   7        6               13             2 
   8        6               14             1

Upvotes: 0

Views: 555

Answers (2)

Karan Bhagat
Karan Bhagat

Reputation: 329

I gave this a try using R. My previous answer was in Python. The program looks very basic since I am not an R programmer, but still gave it a try. At least it will help someone new to R(Hopefully). Notice: Code may be an abomination to R way of programming.

process_dframe <- function(){

    col1 = c(1, 2, 3)
    col2 = c(5, 6, 6)
    new_value = c(0, 0, 0)
    dframe <- data.frame(col1, col2, new_value)
    print(dframe)

    new_val_col_sum <- 0
    col1_increment <- 5
    size <- length(dframe$col1)
    print(size)
    while(new_val_col_sum < 5) {
        if(new_val_col_sum > 0) {
            dframe$col1[min_row] <- sum(dframe$col1[min_row], col1_increment)
        }
        min_sum <- as.integer(.Machine$integer.max)
        min_row <- 0
        for(i in 1:size) {
            crnt_sum <- sum(dframe$col1[i], dframe$col2[i])
            if(crnt_sum < min_sum) {
                min_sum <- crnt_sum
                min_row <- i
            }
        }
        dframe$new_value[min_row] <- sum(dframe$new_value[min_row], 1)
        new_val_col_sum <- sum(new_val_col_sum, 1)
    }
    return(dframe)
}

d <- process_dframe()
print(d)

Output col1 col2 new_value 1 1 5 0 2 2 6 0 3 3 6 0 [1] 3 col1 col2 new_value 1 1 5 1 2 2 6 0 3 3 6 0 col1 col2 new_value 1 6 5 1 2 2 6 1 3 3 6 0 col1 col2 new_value 1 6 5 1 2 7 6 1 3 3 6 1 col1 col2 new_value 1 6 5 2 2 7 6 1 3 8 6 1 col1 col2 new_value 1 11 5 2 2 7 6 2 3 8 6 1

Upvotes: 2

Maurits Evers
Maurits Evers

Reputation: 50668

The following reproduces your expected output and intermediate results

# Initialise and pre-alloc memory
df$`Col1&Col2_sum` <- 0
df$New_Value <- 0

# while loop
while (sum(df$New_Value) < 5) {
    df$`Col1&Col2_sum` <- rowSums(df[, 1:2])
    df$New_Value <- df$New_Value + (df$`Col1&Col2_sum` == min(df$`Col1&Col2_sum`))
    print(df)
    idx <- which.min(df$`Col1&Col2_sum`)
    df$Col1[idx] <- df$Col1[idx] + 5
}
#  Col1 Col2 Col1&Col2_sum New_Value
#1    1    5             6         1
#2    2    6             8         0
#3    3    6             9         0
#  Col1 Col2 Col1&Col2_sum New_Value
#1    6    5            11         1
#2    2    6             8         1
#3    3    6             9         0
#  Col1 Col2 Col1&Col2_sum New_Value
#1    6    5            11         1
#2    7    6            13         1
#3    3    6             9         1
#  Col1 Col2 Col1&Col2_sum New_Value
#1    6    5            11         2
#2    7    6            13         1
#3    8    6            14         1
#  Col1 Col2 Col1&Col2_sum New_Value
#1   11    5            16         2
#2    7    6            13         2
#3    8    6            14         1

You can remove the print statement if not needed, I've only included it to demonstrate the intermediate results. df contains the final output.


Sample data

df <- read.table(text =
    "Col1     Col2
   1        5
   2        6
   3        6", header = T)

Upvotes: 1

Related Questions