1
votes

I have a data.table with many columns: Let's say a simple example:

mm <- data.table( A = 1:4, B = 5:8, C = 5:2, D= c(1,1,1,1))

And a vector containing some of its names as strings: (*)

nn <- c("A", "B", "C")

and I would like cbind the mm content specified by nn as:

1
2
3
4
5
6
7
8
5
4
3
2

Unfortunately cbind(eval(nn)) is not enough in these cases. If A, B and C weren't inside a data.table I could try

cbind(lapply(as.list(noquote(c("a","b"))), get))
or
mapply( function(x) cbind(get(noquote(x))), as.list(nn))

but they don't work properly. The only working method I've found so far is

unlist(lapply(nn,get))

But in my problem they are not independent objects but within the mm data.table, this method doesn't seem to work.

I've also tried

mm[, lapply(nn, get)]

but it says

Error in FUN(X[[i]], ...) : object 'A' not found

lapply(nn,function(x) (mm[,.SDcols=x]))

doesn't work either I've also tried with eval, parse, noquote and other options.

So far I only found this solution:

melt(mm[,.SD,.SDcols=nn])$value

Is there any simpler method?

(*) Coming from grep operations.

1
I prefer your melt approach to the answer below, though you can do melt(mm[, ..nn])$value - Frank
@Frank, why do you prefer the melt approach? - skan
Unlisting preserves names and doesn't warn about combining columns of different types. For example, DT = data.table(a = as.Date("1978/1/1"), b = 11, v = 2L); melt(DT); unlist(DT). Generally, it's because I know what to expect from melt... Extending the example with list columns: DT = data.table(a = as.Date("1978/1/1"), b = 11, v = 2L, k = list(1:2)); unlist(DT); melt(DT, meas=names(DT)) -- seems like the latter is the correct result. - Frank

1 Answers

3
votes

To get a named vector, you can use

mm[, unlist(.SD), .SDcols = nn]

Or, if you need the result as a data.table, then we can simply wrap the j argument inside .()

mm[, .(unlist(.SD)), .SDcols = nn]