5
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

5
  • I don't know the underlying reason, but I see ?as.ITime notes in the first line of the Description that it is "Still experimental!" (as of data.table 1.14.8) so maybe not extensively tested to avoid weird behavior like that. Commented May 20 at 4:49
  • 1
    Try data.table(DateTime,TimeOfDay,Year) |> as.data.frame(). Commented May 20 at 5:09
  • Why does that work when straight to data.frame trips on it? Commented May 20 at 5:50
  • @JonSpring, thanks for checking. I am on data.table version 1.17.2 which is not marked experimental. Commented May 23 at 3:54
  • As for why @jay.sf's solution work, the existing but report says that column name on ITime works for data.table. So once the column name is there in the data.table, converting the table to a data.frame wouldn't loose the column name. Commented May 23 at 3:58

1 Answer 1

8

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"
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for looking into this in details. Found that this has been reported in 2020, but there is no correct fix yet.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.