user1238097
user1238097

Reputation: 87

Data.table and for loops

I was working on problem with data.tables. Basically I am search the data.table for set_a and checking for a Average is greater than 80 and doing some matrix building. My criteria look for a set_a value and if it is greater than 80 I want to paste together only the top value as shown below in my script to create a row composed of set_a, set_b concatenated with the letter a, value and then append another row with set_a, set_b concatenated letter b, value into a master table mn. If it isn't greater than 80 than I want select the 1 and 2 value ordered by Average in descending. I was able to accomplish the first part of the loop but it doesn't continue on for the set_a values b and c. You will also see t where I tried creating a second data table for the else part of the loop but have been unable to access values for the columns like I would normally in data.frames.

Example data_set:
set_a <- c("a","a","a","a","b","b","b","b","c","c","c","c")
set_b <- c("red","red","red","red","red","red","red","red","red","red","red","red")
value <- c(42,68,90,91,22,65,89,98,78,88,91,33)
Average <- c(94,3,2,1,50,40,5,5,80,9,1,1)
a = data.frame(set_a,set_b,value,Average)
library(data.table)
a = data.table(a)

R script

mn <- c() #create matrix to fill
mn0 <- c() #temp matrix
colu = unique(as.character(a$set_a))
colu2 = as.character(a$set_b)
for (i in seq_along(colu))
  {
    if (a[set_a[i] == colu[i], max(Average) > 80])#if the average is greater than 80 paste row variables in table.
  {
      mn <- (cbind(set_a[i],paste0(set_b[i],"_a"),value[i]))
      mn0 <- rbind(mn,mn0)
      mn2 <- (cbind(set_a[i],paste0(set_b[i],"_b"),value[i]))
      mn0 <- rbind(mn0,mn2)
      break
  }else

  {
    t = a[set_a == colu[i],.SD[1:2]] #create a second data table to select for
                                     #first second value  

    mn3 <- cbind(set_a[i],paste0(set_b[i],"_a"),value[i])

    mn0 <- rbind(mn0,mn3)
    mn4 <- cbind(set_a[i],paste0(set_b[i],"_b"),value[i])
    mn0 <- rbind(mn0,mn4)
  }
}

mn0

My current result:

     [,1] [,2]    [,3]
[1,] "a"  "red_a" "42"
[2,] "a"  "red_b" "42"

Desired result:

    [,1] [,2]    [,3]
[1,] "a"  "red_a" "42"
[2,] "a"  "red_b" "42"
[3,] "b"  "red_a" "22"
[4,] "b"  "red_b" "65"
[5,] "c"  "red_a" "78"
[6,] "c"  "red_b" "88"

Upvotes: 0

Views: 98

Answers (1)

Marcelo
Marcelo

Reputation: 4282

You have a break inside the if. It will cause your code to exit the for-loop. Also, on the else block, you need to refer to temporary data.table "t", otherwise, set_a will refer to the data.table "a".

Here is the correct script:

mn <- c() #create matrix to fill
mn0 <- c() #temp matrix
colu = unique(as.character(a$set_a))
colu2 = as.character(a$set_b)

for (i in seq_along(colu))
  {
    if (a[set_a == colu[i], max(Average) > 80])#if the average is greater than 80 paste row variables in table.
  {
      mn <- (cbind(set_a[i],paste0(set_b[i],"_a"),value[i]))
      mn0 <- rbind(mn,mn0)
      mn2 <- (cbind(set_a[i],paste0(set_b[i],"_b"),value[i]))
      mn0 <- rbind(mn0,mn2)
  }else

  {
    t = a[set_a == colu[i],.SD[1:2]] #create a second data table to select for
                                     #first second value  

    mn3 <- cbind(as.character(t$set_a[1]),paste0(t$set_b[1],"_a"),t$value[1])

    mn0 <- rbind(mn0,mn3)
    mn4 <- cbind(as.character(t$set_a[2]),paste0(t$set_b[2],"_b"),t$value[2])
    mn0 <- rbind(mn0,mn4)
  }
}

mn0

Upvotes: 1

Related Questions