How to add multiple columns to a data.frame in one go?

This will get you there:

ddf[xx] <- NA

#   a b  c  d  e  f
#1  1 2 NA NA NA NA
#2  1 2 NA NA NA NA
#3  1 2 NA NA NA NA
#...

You can't directly use something like ddf$xx because this will try to assign to a column called xx rather than interpreting xx. You need to use [ and [<- functions, using the square brackets when you are dealing with a character string/vector - like ddf["columnname"] or ddf[c("col1","col2")], or a stored vector like your ddf[xx].

The reason why it selects columns is because data.frames are lists essentially:

is.list(ddf)
#[1] TRUE

as.list(ddf)
#$a
# [1] 1 1 1 1 1 1 1 1 1 1
# 
#$b
# [1] 2 2 2 2 2 2 2 2 2 2

...with each column corresponding to a list entry. So if you don't use a comma to specify a row, like ddf["name",] or a column like ddf[,"name"], you get the column by default.


In the case that you are working with a 0-row dataset, you can not use a value like NA as the replacement. Instead, replace with list(character(0)) where character(0) can be substituted for numeric(0), integer(0), logical(0) etc, depending on the class you want for your new columns.

ddf <- data.frame(a=character())
xx <- c("c", "d", "e", "f")
ddf[xx] <- list(character(0))
ddf
#[1] a c d e f
#<0 rows> (or 0-length row.names)

This seems to succeed:

> cbind(ddf, setNames( lapply(xx, function(x) x=NA), xx) )
   a b  c  d  e  f
1  1 2 NA NA NA NA
2  1 2 NA NA NA NA
3  1 2 NA NA NA NA
4  1 2 NA NA NA NA
5  1 2 NA NA NA NA
6  1 2 NA NA NA NA
7  1 2 NA NA NA NA
8  1 2 NA NA NA NA
9  1 2 NA NA NA NA
10 1 2 NA NA NA NA