Two alternative possibilities in which the data.table attributes are especially important are of interest when speed and memory are a problem:
base R:
Bind data files together to one:
df3 <- rbind(df1,df2)
Create a reference data block with all possible combinations of Month and variable using expand.grid :
ref <- expand.grid(Month = unique(df3$Month), variable = unique(df3$variable))
Combine them with all.x=TRUE to ensure that the missing combinations are filled with NA values:
merge(ref, df3, by = c("Month", "variable"), all.x = TRUE)
Or (thanx to @PierreLafortune):
merge(ref, df3, by=1:2, all.x = TRUE)
data.table:
Bind dataframes to one with "rbindlist", which returns "data.table":
library(data.table) DT <- rbindlist(list(df1,df2))
Join the link to make sure all combinations are present and the missing ones are filled with NA:
DT[CJ(Month, variable, unique = TRUE), on = c(Month="V1", variable="V2")]
All together in one call:
DT <- rbindlist(list(df1,df2))[CJ(Month, variable, unique = TRUE), on = c(Month="V1", variable="V2")]
An alternative is wrapping rbindlist in setkey and then expanding with CJ (cross join):
DT <- setkey(rbindlist(list(df1,df2)), Month, variable)[CJ(Month, variable, unique = TRUE)]