Update: The behaviour DT[, list(list(.)), by=.]
sometimes resulted in wrong results in R version >= 3.1.0. This is now fixed in commit #1280 in the current development version of data.table v1.9.3. From NEWS:
DT[, list(list(.)), by=.]
returns correct results in R >=3.1.0 as well. The bug was due to recent (welcoming) changes in R v3.1.0 wherelist(.)
does not result in a copy. Closes #481.
With this update, it's not necessary for I()
anymore. You can just do: DT[, list(list(.)), by=.]
as before.
This seems to be a similar issue as the known bug #5585. In your case, I think you could just use
dt[, paste(letter, collapse=","), by = id]
to fix your problem.
As @ilir pointed out, if it is actually desirable to get a list (rather than the displayed character), you could use the workaround suggested in the bug report:
dt[, list(list(I(letter))), by = id]