rdata.table

Why don't ITime columns in data.frame get the column name from vector?


library(data.table)

DateTime<-as.POSIXct(c("2025-05-16 00:00:02 CDT", "2025-05-16 00:00:03 CDT", "2025-05-16 00:00:06 CDT", "2025-05-16 00:00:07 CDT"))
TimeOfDay<-as.ITime(DateTime)
Year<-year(DateTime)
data.frame(DateTime,TimeOfDay,Year)

Gives the result:

             DateTime       V1 Year
1 2025-05-16 00:00:02 00:00:02 2025
2 2025-05-16 00:00:03 00:00:03 2025
3 2025-05-16 00:00:06 00:00:06 2025
4 2025-05-16 00:00:07 00:00:07 2025

Why is the second column named 'V1' and not TimeOfDay?

I can set the name separately, but I am curious why it happens with ITime column only. I have tried factors, numeric etc as columns and they work fine. I am using R 4.3.3


Solution

  • I have reported this to the issue tracker.

    The reason is that the data.table devs took a shortcut and implemented data.table:::as.data.frame.ITime in a way that always sets "V1" as column name. We can see an unconditional setattr(ans, "names", "V1") in the code of that method.

    In contrast, the as.data.frame generic and methods in the base package have an optional argument, for which the documentation says:

    logical. If TRUE, setting row names and converting column names (to syntactic names: see make.names) is optional. Note that all of R's base package as.data.frame() methods use optional only for column names treatment, basically with the meaning of data.frame(*, check.names = !optional). See also the make.names argument of the matrix method.

    as.data.frame.vector and the deprecated as.data.frame.POSIXct also have an argument nm = deparse1(substitute(x)) which by default deparses the symbol passed to the first argument to be used as column name.

    To demonstrate:

    names(as.data.frame(TimeOfDay, optional = FALSE))
    #[1] "V1"
    
    names(as.data.frame(DateTime, optional = FALSE))
    #[1] "DateTime"