socialscientist
socialscientist

Reputation: 4242

R: Nested for-loop to compare rows and build new data frame

I created two nested for loops to complete the following:

Iterating through each column that is not the first column:

Store the results of all iterations across all columns and rows in a df.

The code below creates some test data but produces a Value "out" that is NULL (empty). Any recommendations?

# Create df
a <- rnorm(5)
b <- c(rnorm(3),NA,rnorm(1))
c <- rnorm(5)
df <- data.frame(a,b,c)

rows <- nrow(df)  # rows
cols <- ncol(df)  # cols

out <- for (c in 2:cols){
          for (r in 1:(rows - 1)){
            ifelse(
                    is.na(df[r,c]),
                    NA,
                    df[r, c] <- df[r, c] < df[rows, c])
           }
        }

Upvotes: 0

Views: 1545

Answers (2)

akrun
akrun

Reputation: 887148

Here is another option. We can replicate the last row to make the dimensions of both datasets equal and then do the > to get a logical index, which can be coerced to binary by wrapping with +.

+(df[-nrow(df),] > df[nrow(df),][col(df[-nrow(df),])])
#  a  b c
#1 0  0 1
#2 1  0 1
#3 0  1 1
#4 1 NA 1

Upvotes: 1

thelatemail
thelatemail

Reputation: 93813

There's no need for looping at all. Use a vectorised function like sweep to compare via > your last row - df[nrow(df),] vs all the other rows df[-nrow(df),]:

df
#           a          b           c
#1 -0.2739735  0.5095727  0.30664838
#2  0.7613023 -0.1509454 -0.08818313
#3 -0.4781940  1.5760307  0.46769601
#4  1.1754130         NA  0.33394212
#5  0.5448537  1.0493805 -0.10528847

sweep(df[-nrow(df),], 2, unlist(df[nrow(df),]), FUN=`>`)
#      a     b    c
#1 FALSE FALSE TRUE
#2  TRUE FALSE TRUE
#3 FALSE  TRUE TRUE
#4  TRUE    NA TRUE

sweep(df[-nrow(df),], 2, unlist(df[nrow(df),]), FUN=`>`) + 0
#  a  b c
#1 0  0 1
#2 1  0 1
#3 0  1 1
#4 1 NA 1

Upvotes: 1

Related Questions