I don't know if the following code is very elegant but it works. It's a double *apply loop.
Quoting the question:
I could easily write code that processes a and calls setattr 5 times to accomplish this. But I'm hoping there is a better way.
The problem is that the name in setattr must be a length 1 character string, so setattr will always have to be called 5 times. In the code below this is done in disguise of a double loop.
The example data.table comes from the 3rd DT in help("setattr").
library(data.table)
DT <- data.table(x1 = 1:3, y = 4:6, x3 = 7:9)
a <- list(x1=list(label='X1', units='mm'),
x3=list(label='X3', comment='collected remotely', format='type 3'))
mapply(function(x, a){
lapply(names(a), function(na) setattr(DT[[x]], na, a[[na]]))
}, names(a), a)
attributes(DT$x1)
#$label
#[1] "X1"
#
#$units
#[1] "mm"
attributes(DT$x3)
#$label
#[1] "X3"
#
#$comment
#[1] "collected remotely"
#
#$format
#[1] "type 3"
Note. In order to avoid the ugly output from the loops, wrap them in invisible:
invisible(
mapply(function(x, a){
lapply(names(a), function(na) setattr(DT[[x]], na, a[[na]]))
}, names(a), a)
)
Edit
The following code is simpler.
lapply(names(a), function(x){
lapply(names(a[[x]]), function(y) setattr(DT[[x]], y, a[[x]][[y]]))
})