In order to make my function more failsafe, I need to create an empty data.table, which does have a specific number of columns and a predefined data.type. This is to allow the later call to dplyr::union even though the data.table is empty.
Therefore, I would like to create an empty data.table and define the data types of the columns directly. This works for numeric or character columns, but fails for Date columns.
I found a possible solution by using entry 2.4 from the data.table FAQ, but it seems a bit weird to first fill the data.table with wrong values and remove them afterwards. FAQ 2.4
Code to replicate the issue:
library(data.table)
library(dplyr)
dt.empty <- data.table("Date" = character() , "Char.Vector" = character() , "Key.Variable" = character() , "ExchangeRate" = numeric()
)
dt.Union <- data.table( "Date" = as.Date(c("2000-01-01", "2001-01-01")) , "Char.Vector" = as.character(c("a", "b")) , "Key.Variable" = as.character(c("x1", "x2")) , "ExchangeRate" = as.numeric(c(2,1.4))
)
dplyr::union(dt.Union , dt.empty)
Error: not compatible:
- Incompatible type for column `Date`: x Date, y character
- Incompatible type for column `ExchangeRate`: x numeric, y characterI could solve this by using dt.Union[0] to create dt.empty, but I thought perhaps there exists an easier way to do this.
1 Answer
You can follow the advice of FAQ 2.4 the first time if you're not sure how to write a length-zero vector for some class:
> dput(dt.Union[0])
structure(list(Date = structure(numeric(0), class = "Date"), Char.Vector = character(0), Key.Variable = character(0), ExchangeRate = numeric(0)), row.names = c(NA, 0L), class = c("data.table",
"data.frame"), .internal.selfref = <pointer: 0x7ffd8d0ebee0>)You can take the list(...) part out and your code becomes
myDT = setDT(list( Date = structure(numeric(0), class = "Date"), Char.Vector = character(0), Key.Variable = character(0), ExchangeRate = numeric(0)
))More generally, dput(x[0L]) will show code to recreate the zero-length version of any vector.