在 R 中创建单独的日期和时间列

Creating separate date and time columns in R

提问人:cake2244 提问时间:11/7/2023 最后编辑:cake2244 更新时间:11/7/2023 访问量:65

问:

因此,我有一个组合的日期和时间列,如下所示(我们称此列为日期和时间)。

日期和时间
10/28/2023 23:00:00
9/22/2023 11:47:00
9/22/2023 11:47:00
8/24/2023 11:58:00

我想将日期和时间分成两个单独的条目,因此一列用于日期,一列用于时间。我将如何在 R 中执行此操作?

日期 时间
10/28/2023 下午11:00:00
9/22/2023 上午11:47:00
9/22/2023 上午11:47:00
8/24/2023 上午11:58:00

为了提供更多的见解,日期和时间表示为一个字符。我基本上想把它分成两列,以提高可解释性和可读性。我可能希望根据特定的日期范围筛选记录,当日期和时间分开时,这会更容易。当日期和时间不同时,对时间间隔执行算术运算也更直接。

我尝试过的代码在这里,但我对 R 相当了解,所以代码没有成功。我本质上是试图更新“日期和时间”列以仅包含时间,并创建一个单独的日期列,该列从组合的日期和时间中提取日期。

但是,我认为最好保留组合列并只制作两个单独的列。

# create a new column called Date
# where we extract the date from Time
# update Time format to only include the time
data <- data %>% 
mutate(`Time` = strptime(`Time`, format = "%I:%M:%S %p"),
`Date` = as.Date(`Time`),
`Time` = format(`Time`, format = "%H:%M:%S"))
r 日期 时间

评论

1赞 r2evans 11/7/2023
请不要发布(仅)代码/数据/错误的图像:它会破坏屏幕阅读器,并且无法复制或搜索(参考:meta.stackoverflow.com/a/285557xkcd.com/2116)。请将代码、控制台输出或数据(例如,或 的输出)直接包含在代码块中。data.frame(...)dput(head(x))
2赞 r2evans 11/7/2023
请访问您之前的问题;对于每个答案,如果答案解决了您的问题,请考虑通过单击复选标记来接受它(也阅读)。这向更广泛的社区表明您已经找到了解决方案,并为回答者和您自己赢得了一些声誉。(没有义务这样做。
2赞 r2evans 11/7/2023
我明白,很多时候问题都是基于专有数据的,这很好。但是,这里有两件事:(1)您不必向我们提供实际数据,只需提供与您的真实数据具有足够代表性的数据,以便我们可以完成工作;(2)我不会花时间将数据转录成可用的东西。因此,如果你不能花时间拿出合理的、有代表性的样本数据,那么我认为你要求我们很多人从你的数据图像中工作,并假设我们会自己输入所有内容。
1赞 cake2244 11/7/2023
我现在将数据作为文本添加
1赞 r2evans 11/7/2023
此外,您还做了哪些研究?你试过什么代码?另外,为什么需要将其拆分为日期和时间?关于基于模式吐出文本、转换为真实时间戳,然后从 -class 值中提取“时间”等,有很多问题。POSIXt

答:

0赞 Jon Spring 11/7/2023 #1
data.frame(
  stringsAsFactors = FALSE,
     Date.and.Time = c("10/28/2023 11:00:00 PM",
                       "9/22/2023 11:47:00 AM","9/22/2023 11:47:00 AM",
                       "8/24/2023 11:58:00 AM")
) |> mutate(dt = lubridate::mdy_hms(Date.and.Time),
            Date = lubridate::as_date(dt),
            Time = format(dt, format = "%H:%M:%S"),
            Time2 = hms::as_hms(dt))

           Date.and.Time                  dt       Date     Time    Time2
1 10/28/2023 11:00:00 PM 2023-10-28 23:00:00 2023-10-28 23:00:00 23:00:00
2  9/22/2023 11:47:00 AM 2023-09-22 11:47:00 2023-09-22 11:47:00 11:47:00
3  9/22/2023 11:47:00 AM 2023-09-22 11:47:00 2023-09-22 11:47:00 11:47:00
4  8/24/2023 11:58:00 AM 2023-08-24 11:58:00 2023-08-24 11:58:00 11:58:00
 

几点观察:

  1. 如果可以尽早将日期设置为 R 数据类型 Date 或 POSIXct (datetime),则计算日期或日期时间将是最容易的。这些数据将始终以 YYYY-MM-DD 顺序显示 -- 任何其他顺序都表明您的数据是人类可读的,但不能直接计算。
  2. 此处格式化的时间列计算起来会很痛苦; Time2 会更有用——你可以增加一个小时,比较两个时间,等等。如果任何计算涉及多天,则更有用。根据我自己的经验,将日期和时间分开会使筛选和比较更加复杂,但在某些领域(如可视化或报告)可能会有所帮助。dt
1赞 StatsStudent 11/7/2023 #2

我强烈建议您不要将日期和时间分隔到单独的字段中。相反,您应该尝试了解日期时间字段的工作原理以及如何利用它们来发挥自己的优势。在我看来,您对日期/时间的算术操作以及日期和时间的过滤的担忧并不是拆分日期和时间的有力论据,因为 R 以及整洁和润滑包非常容易地处理所有这些。在下面的代码中,我设置了一个日期字符向量,将其转换为日期时间字段,然后向您展示以日期时间格式操作日期是多么容易,特别是解决您对日期/时间的数学操作和查询日期/时间的担忧。

# Load the tidyvere and lubridate packages
library(tidyverse)
library(lubridate)
        
# Create a character vector of "dates and times."
my_df <- data.frame(mydate = c("10/28/2023 11:00:00 PM", 
                                "9/22/2023 11:47:00 AM", 
                                "9/22/2023 11:47:00 AM", 
                                "8/24/2023 11:58:00 AM"))
        
# Convert to datetime format
(my_df2 <- my_df %>% 
    mutate(mydate_dt = as_datetime(mydate, format="%m/%d/%Y %I:%M:%S %p")))    

                      mydate           mydate_dt
    1 10/28/2023 11:00:00 PM 2023-10-28 23:00:00
    2  9/22/2023 11:47:00 AM 2023-09-22 11:47:00
    3  9/22/2023 11:47:00 AM 2023-09-22 11:47:00
    4  8/24/2023 11:58:00 AM 2023-08-24 11:58:00    

# Query all records be between 08/20/2023 and 09/23/2023
(my_df2 %>% filter(
  between(mydate_dt, 
          as.Date("2023-08-20"), 
          as.Date("2023-09-23"))
  ))
                 mydate           mydate_dt
1 9/22/2023 11:47:00 AM 2023-09-22 11:47:00
2 9/22/2023 11:47:00 AM 2023-09-22 11:47:00
3 8/24/2023 11:58:00 AM 2023-08-24 11:58:00

    
# Add 4 hours to the time
(my_df2 %>% mutate(time_plus_three=mydate_dt+hours(4)))

                  mydate           mydate_dt     time_plus_three
1 10/28/2023 11:00:00 PM 2023-10-28 23:00:00 2023-10-29 03:00:00
2  9/22/2023 11:47:00 AM 2023-09-22 11:47:00 2023-09-22 15:47:00
3  9/22/2023 11:47:00 AM 2023-09-22 11:47:00 2023-09-22 15:47:00
4  8/24/2023 11:58:00 AM 2023-08-24 11:58:00 2023-08-24 15:58:00
    
# Add 3 days to the time
(my_df2 %>% mutate(time_plus_three=mydate_dt+days(3)))

                  mydate           mydate_dt     time_plus_three
1 10/28/2023 11:00:00 PM 2023-10-28 23:00:00 2023-10-31 23:00:00
2  9/22/2023 11:47:00 AM 2023-09-22 11:47:00 2023-09-25 11:47:00
3  9/22/2023 11:47:00 AM 2023-09-22 11:47:00 2023-09-25 11:47:00
4  8/24/2023 11:58:00 AM 2023-08-24 11:58:00 2023-08-27 11:58:00
    
#Display and date and time only in separate fields and formatted in different ways.
(my_df2 %>% mutate(
                  time_only = format(mydate_dt, "%I:%M:%S %p"),
                  date_only = format(mydate_dt, "%m/%d/%Y"),
                  time_24   = format(mydate_dt, "%T")
                  ))


                  mydate           mydate_dt   time_only  date_only  time_24
1 10/28/2023 11:00:00 PM 2023-10-28 23:00:00 11:00:00 PM 10/28/2023 23:00:00
2  9/22/2023 11:47:00 AM 2023-09-22 11:47:00 11:47:00 AM 09/22/2023 11:47:00
3  9/22/2023 11:47:00 AM 2023-09-22 11:47:00 11:47:00 AM 09/22/2023 11:47:00
4  8/24/2023 11:58:00 AM 2023-08-24 11:58:00 11:58:00 AM 08/24/2023 11:58:00