如何在具有额外信息的R中将列转换为日期格式

How to convert column into date format in R that has extra information

我想对其余数据(约 200 万行)使用某种正则表达式函数来提取相关日期信息(理想情况下日期格式为日、月和时间,因为年份仅为 2009 年~200 万行)。

我有一个看起来像这样的专栏:

ID | created_at
1    Mon Apr 06 22:19:45 PDT 2009
2    Mon Apr 06 22:19:49 PDT 2009

我应用这两个函数来提取“日”并从末尾删除 'PDT 2009',但现在我想将其余列设为日期格式以用于绘图目的。

df$Day <- sub("([A-Za-z]+).*", "\1", df$created_at) ## Extract first word

df$delete <- gsub("\PDT.*","", df$created_at) ## Delete everything after PDT starts

期望的结果:

ID | created_at                    | Month  | Day  | Time
1    Mon Apr 06 22:19:45 PDT 2009    Apr      Mon    22:19:45
2    Mon Apr 06 22:19:49 PDT 2009    Apr      Mon    22:19:49

我想这可能对你有帮助

图书馆

library(tidyverse)
library(lubridate)

数据

df <- 
  tibble(
    created_at = c("Mon Apr 06 22:19:45 PDT 2009","Mon Apr 06 22:19:49 PDT 2009") 
  )

代码

df %>% 
  separate(
    col = created_at,
    into = c("wday","month","day","time","type","year"),
    sep = " ",
    remove = FALSE
    ) %>% 
  mutate(
    day = as.numeric(day),
    year = as.numeric(year),
    month_num = which(month.abb == month),
    time = hms(time),
    date = lubridate::make_date(year = year,month = month_num,day = day)
  )

结果

# A tibble: 2 x 9
  created_at                   wday  month   day time        type   year month_num date      
  <chr>                        <chr> <chr> <dbl> <Period>    <chr> <dbl>     <int> <date>    
1 Mon Apr 06 22:19:45 PDT 2009 Mon   Apr       6 22H 19M 45S PDT    2009         4 2009-04-06
2 Mon Apr 06 22:19:49 PDT 2009 Mon   Apr       6 22H 19M 49S PDT    2009         4 2009-04-06

您不需要使用任何正则表达式,只需使用常规日期格式即可。您可以在 here?strptime() 中找到很好的概述。你只需要调整分隔符。这应该比使用正则表达式、拆分等更容易、更有效...

一旦您拥有原生 R 日期时间格式 POSIXltPOSIXt,您就可以轻松提取所有与日期相关的信息。

strptime(x      = "Mon Apr 06 22:19:45 PDT 2009",
         format = "%a %b %d %H:%M:%S PDT %Y")
#> [1] "2009-04-06 22:19:45 CEST"

这是一种将 str_splitmap_char 结合使用的方法:

library(tidyverse)
df %>% 
    mutate(elements = str_split(created_at, fixed(" "), n=6)) %>% 
    mutate(Month = map_chr(elements, 2),
           Day = map_chr(elements, 1),
           Time = map_chr(elements, 4), .keep="unused"
           )

输出:

  ID                   created_at Month Day     Time
1  1 Mon Apr 06 22:19:45 PDT 2009   Apr Mon 22:19:45
2  2 Mon Apr 06 22:19:49 PDT 2009   Apr Mon 22:19:49

您可以使用以下解决方案:

library(dplyr)

df %>%
  mutate(ID = row_number(), 
         Month = gsub("(?:[A-Za-z]+)\s([A-Za-z]+).*", "\1", created_at, perl = TRUE),
         Day = gsub("([A-Za-z]+).*", "\1", created_at, perl = TRUE), 
         Time = gsub(".*(\d{2}:\d{2}:\d{2}).*", "\1", created_at, perl = TRUE)) %>%
  relocate(ID)

# A tibble: 2 x 5
     ID created_at                   Month Day   Time    
  <int> <chr>                        <chr> <chr> <chr>   
1     1 Mon Apr 06 22:19:45 PDT 2009 Apr   Mon   22:19:45
2     2 Mon Apr 06 22:19:49 PDT 2009 Apr   Mon   22:19:49

如果您刚好在 MonthDayTime 之后,为什么不使用 tidyverse 中的 extract:

library(tidyr)
df %>%
  extract(col = created_at, 
          into = c('Month', 'Day', 'Time'), 
          regex = "([A-Za-z]+)\s([A-Za-z]+)\s\d{2}\s([\d:]+)")
  Month Day     Time
1   Mon Apr 22:19:45
2   Mon Apr 22:19:49

在这里,我们使用圆括号语法 (...) 定义了三个捕获组,以识别我们想要 extract 到三列中的子字符串。

如果您还需要 created_at 的原始形式,只需将结果存储为 df1 并使用 cbind:

cbind(df, df1)
                    created_at Month Day     Time
1 Mon Apr 06 22:19:45 PDT 2009   Mon Apr 22:19:45
2 Mon Apr 06 22:19:49 PDT 2009   Mon Apr 22:19:49

数据:

df <- 
  data.frame(
    created_at = c("Mon Apr 06 22:19:45 PDT 2009","Mon Apr 06 22:19:49 PDT 2009") 
  )