【问题标题】:Trying to split two date-time fields into separate date and time fields in RStudio尝试在 RStudio 中将两个日期时间字段拆分为单独的日期和时间字段
【发布时间】:2021-09-18 00:35:24
【问题描述】:

我是 R/RStudio 的新手。我有一个数据框,它有两个日期时间,started_at 和 end_at。我想将它们分成单独的日期和时间列。我已经想出了如何拆分一个或另一个,但我正在努力弄清楚两者,除了拆分一个,创建一个新的数据框,然后拆分另一个。有没有更简单/更快的方法?我目前正在使用变异和分离。

非常感谢您的帮助或建议!

trip_data %>% mutate(started_at = ymd_hms(started_at)) %>%
  separate(started_at, into = c("start_date", "start_time"), sep = " ", remove = FALSE)

我希望我这样做是对的,如果我做错了,我深表歉意。这是我可重现的例子。我有三列,假设有数千行,我需要分隔两个日期时间列,而不是另一个。谢谢你休艾伦在这里开始。或者,正如休艾伦建议的那样,我可能只需要将 ymd 拉到单独的列中,以便计算间隔。

tibble(
  start = '2021-09-18 16:45:32', 
  end = '2021-09-18 16:50:15',
  name = 'trip'
) %>% 
  {. ->> my_data}

【问题讨论】:

标签: r lubridate


【解决方案1】:

如果我们想使用separate 循环多个列,请使用for 循环

library(dplyr)
library(tidyr)
library(stringr)
for(nm in c('started_at', 'ended_at')) {
  trip_data <- trip_data %>%
     separate(!! rlang::sym(nm), into = str_c(str_remove(nm, '_at'), 
       c('_date', '_time')), sep = " ", remove = FALSE)
}

数据

trip_data <- structure(list(started_at = "2021-09-17 20:51:59", ended_at = "2021-09-17 20:52:04"), row.names = c(NA, 
-1L), class = c("tbl_df", "tbl", "data.frame"))

【讨论】:

    【解决方案2】:

    在 R 中处理日期和日期时间时,lubridate 包是您的朋友。它有许多有用的功能,并且有专门设计用于返回日期时间的日期和时间组件的功能。

    如果您是 R 新手,我强烈建议您阅读和通读 R for Data Science ebook,尤其是 Chapter 16 - Dates and times,以便使用 lubridate 包很好地了解日期和时间处理。

    对于您的示例,您只有两列要提取日期和时间,这可以通过为每一列重复相同的代码相对容易地完成。如果您有很多列,@akrun 建议的 for 循环可能是可行的,或者您可以将数据从宽格式转换为长格式。

    首先,我们制作一些样本数据

    tibble(
      start = '2021-09-18 16:45:32', 
      end = '2021-09-18 16:50:15'
    ) %>% 
      {. ->> my_data}
    
    my_data 
    
    # # A tibble: 1 x 2
    # start               end                
    # <chr>               <chr>              
    # 2021-09-18 16:45:32 2021-09-18 16:50:15
    

    到目前为止,日期时间都是字符格式的(如 tibble 预览中列名下的 &lt;chr&gt; 所示)。因此,接下来我们使用lubridate::ymd_hms() 将它们转换为“正确的”日期时间格式。 ymd_hms() 采用以 'YYYY-MM-DD HH:MM:SS' 样式排列的字符格式日期时间,并将其转换为 R 中的日期时间 dttm 格式。

    my_data %>% 
      mutate_all(ymd_hms) %>% 
      {. ->> my_data_2}
    
    my_data_2
    
    # # A tibble: 1 x 2
    # start               end                
    # <dttm>              <dttm>             
    # 2021-09-18 16:45:32 2021-09-18 16:50:15
    

    然后,我们可以使用lubridate::date() 仅提取日期时间的“日期”部分,并使用hms::as_hms 提取“时间”部分(参见this answer 解释hms::as_hms)。

    my_data_2 %>% 
      mutate(
        start_date = date(start), 
        start_time = hms::as_hms(start), 
        end_date = date(end), 
        end_time = hms::as_hms(end)
      ) %>% 
      {. ->> my_data_3}
    
    my_data_3
    
    # # A tibble: 1 x 6
    # start               end                 start_date start_time end_date   end_time
    # <dttm>              <dttm>              <date>     <time>     <date>     <time>  
    # 2021-09-18 16:45:32 2021-09-18 16:50:15 2021-09-18 16:45:32   2021-09-18 16:50:15
    

    根据您想要做什么,将您的“时间”存储为日期时间而不仅仅是时间组件可能是明智之举。这使得持续时间或时间差的计算更容易,尤其是当时间段跨越多个日期时。

    此外,lubridate 还可以提取单独的时间组件,例如小时、分钟和秒,如果需要的话。例如,仅查找 start 列的这些组件:

    my_data %>% 
      select(start) %>% 
      mutate(
        start_hour = hour(start), 
        start_min = minute(start),
        start_sec = second(start)
      )
    
    # # A tibble: 1 x 4
    # start               start_hour start_min start_sec
    # <chr>                    <int>     <int>     <dbl>
    # 2021-09-18 16:45:32         16        45        32
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-04-25
      • 1970-01-01
      • 2013-08-29
      • 2018-08-28
      • 1970-01-01
      • 2018-01-14
      • 1970-01-01
      相关资源
      最近更新 更多