1

I have a data.table like this:

> dt<-data.table(F=rep(c('a','b','c'),each=2), fix=c(10:15),a=c(1:6), b=c(2:7),c=c(3:8))
> dt
   F fix a b c
1: a  10 1 2 3
2: a  11 2 3 4
3: b  12 3 4 5
4: b  13 4 5 6
5: c  14 5 6 7
6: c  15 6 7 8

The column F stores the column to be extract for each row. So for the first 2 records column, the column 'a' will be extract while the column 'b' will be extracted for the 3 and 4 record. The 'fix' will be kept for each record. The ideal output should be like this:

   F  fix new
1: a  10   1 
2: a  11   2
3: b  12   4
4: b  13   5
5: c  14   7
6: c  15   8
YYY
  • 605
  • 3
  • 8
  • 16

4 Answers4

5

You can use .BY to extract the column from .SD

dt[, .(fix = fix, new = .SD[[.BY$F]]), by = F]
##    F fix new
## 1: a  10   1
## 2: a  11   2
## 3: b  12   4
## 4: b  13   5
## 5: c  14   7
## 6: c  15   8
MichaelChirico
  • 33,841
  • 14
  • 113
  • 198
shadow
  • 21,823
  • 4
  • 63
  • 77
2

You could also do

 melt(dt, id.var=c('F', 'fix'), value.name='new')[F==variable][, 
                         variable:=NULL][]
 #   F fix    new
 #1: a  10     1
 #2: a  11     2
 #3: b  12     4
 #4: b  13     5
 #5: c  14     7
 #6: c  15     8
akrun
  • 874,273
  • 37
  • 540
  • 662
1

One possibility is using lapply to each element of the new column:

dt$new = unlist(lapply(1:nrow(dt), function(ii){ return(dt[ii, dt$F[ii]])}))
Math
  • 2,399
  • 2
  • 20
  • 22
1

If you convert this to a data.frame, you can use the following:

> x <- as.data.frame(dt)
> within(x, new <- x[cbind(1:6, match(x$F, names(x)))])[,c(1,2,6)]
  F fix new
1 a  10   1
2 a  11   2
3 b  12   4
4 b  13   5
5 c  14   7
6 c  15   8
Thomas
  • 43,637
  • 12
  • 109
  • 140