title: Elegantly assigning multiple columns in data.table with lapply()
body: <p>I am trying to figure out an elegant way to use <code>:=</code> assignment to replace many columns at once in a <code>data.table</code> by applying a shared function. A typical use of this might be to apply a string function (e.g., <code>gsub</code>) to all character columns in a table. It is not difficult to extend the <code>data.frame</code> way of doing this to a <code>data.table</code>, but I'm looking for a method consistent with the <code>data.table</code> way of doing things.</p>
  
  <p>For example:</p>
  
  <pre><code>library(data.table)
  
  m &lt;- matrix(runif(10000), nrow = 100)
  df &lt;- df1 &lt;- df2 &lt;- df3 &lt;- as.data.frame(m)
  dt &lt;- as.data.table(df)
  head(names(df))
  head(names(dt))
  
  ## replace V20-V100 with sqrt
  
  # data.frame approach
  # by column numbers
  df1[20:100] &lt;- lapply(df1[20:100], sqrt)
  # by reference to column numbers
  v &lt;- 20:100
  df2[v] &lt;- lapply(df2[v], sqrt)
  # by reference to column names
  n &lt;- paste0("V", 20:100)
  df3[n] &lt;- lapply(df3[n], sqrt)
  
  # data.table approach
  # by reference to column names
  n &lt;- paste0("V", 20:100)
  dt[, n] &lt;- lapply(dt[, n, with = FALSE], sqrt)
  </code></pre>
  
  <p>I understand it is more efficient to loop over a vector of column names using <code>:=</code> to assign:</p>
  
  <pre><code>for (col in paste0("V", 20:100)) dt[, col := sqrt(dt[[col]]), with = FALSE]
  </code></pre>
  
  <p>I don't like this because I don't like reference the <code>data.table</code> in a <code>j</code> expression. I also know that I can use <code>:=</code> to assign with <code>lapply</code> given that I know the column names:</p>
  
  <pre><code>dt[, c("V20", "V30", "V40", "V50", "V60") := lapply(list(V20, V30, V40, V50, V60), sqrt)]
  </code></pre>
  
  <p>(You could extend this by building an expression with unknown column names.)</p>
  
  <p>Below are the ideas I tried on this, but I wasn't able to get them to work. Am I making a mistake, or is there another approach I'm missing?</p>
  
  <pre><code># possible data.table approaches?
  # by reference to column names; assignment works, but not lapply
  n &lt;- paste0("V", 20:100)
  dt[, n := lapply(n, sqrt), with = FALSE]
  # by (smaller for example) list; lapply works, but not assignment
  dt[, list(list(V20, V30, V40, V50, V60)) := lapply(list(V20, V30, V40, V50, V60), sqrt)]
  # by reference to list; neither assignment nor lapply work
  l &lt;- parse(text = paste("list(", paste(paste0("V", 20:100), collapse = ", "), ")"))
  dt[, eval(l) := lapply(eval(l), sqrt)]
  </code></pre>