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
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"