As Frank noted, the problem is that there are (somewhat invisible) several different types of NA . The one that is created when you type NA on the command line has the "logical" class, but there are also NA_integer_ , NA_real_ , NA_character_ and NA_complex_ .
In the first example, the initial data.table sets the class of column b to “character”, and the NA in the second data.table then forced to NA_character_ . In the second example, however, the NA in the first data.table sets column b to the “logical” class, and when the same column in the second data table is forced to “logical”, it is converted to the logical NA. (Try as.logical("x") to see why.)
This is all quite complicated (to formulate, at least), but there is a fairly simple solution. Just create a 1-line data.table template and add it to every data.table you want rbind() . It sets the class of each column as what you want, regardless of what data.table follows it in the list passed to rbind() , and it can be truncated when everything else is connected together.
library(data.table)
Josh o'brien
source share