0

How can the CJ-command be run with string as input? The following MNWE illustrates what is needed:

library(data.table)
# This is the desired output (when needed.cols==2)
dt.wanted <- CJ(X.1=c(1L, 2L), X.2=c(1L, 2L))
# Here is an example with needed.cols as variable
needed.cols <- 2L
use.text <- paste0("X.", 1L:needed.cols, "=c(1L, 2L)", collapse=", ")
# Here are some failing attempts
dt.fail <- CJ(use.text)
dt.fail <- CJ(eval(use.text))
dt.fail <- CJ(get(use.text))

So it is the use.text I want to make scriptable (because it varies, not only with needed.cols).

Chris
  • 2,256
  • 1
  • 19
  • 41

2 Answers2

1

The get-function is the standard way of promoting a character value to a true R name value.

Is this what you want:

col.wanted =2
dt.wanted[ , get(paste0("X.", col.wanted) )]
#[1] 1 2 1 2

Getting multiple columns based on evaluation of a more complex expression might require somewhat more baroque efforts:

> use.text <- paste0("list(", paste0("X.", 1L:needed.cols, collapse=", "),")")
> use.text
[1] "list(X.1, X.2)"
> dt.wanted[ , eval(use.text)]
[1] "list(X.1, X.2)"
> dt.wanted[ , parse(text=use.text)]
expression(list(X.1, X.2))

> dt.wanted[ , eval(parse(text=use.text))]
   X.1 X.2
1:   1   1
2:   1   2
3:   2   1
4:   2   2
IRTFM
  • 258,963
  • 21
  • 364
  • 487
1

IIUC, you are looking for a function to pass a list of arguments into ... of a function. You can do it using do.call as follows:

do.call(CJ, eval(parse(text=paste0("list(",use.text,")"))))

Hope that is what you are looking for...

chinsoon12
  • 25,005
  • 4
  • 25
  • 35