如何将数据框列中的所有日期时间转换为 R 中的特定日期时间格式(当 csv 文件以不同格式存储它们时)
how to convert all datetimes in a dataframe column into a particular datetime format in R (when the csv file has stored them in different formats)
这似乎是一个愚蠢的问题,但它让我花了好几天的时间首先确定问题是什么,现在试图解决它!
我有一个数据框,其中有一列填满了日期时间。这个数据框是一系列不同处理步骤的产物,这些步骤应用于一系列单独的文件,这些文件在某个时候合并为一个文件(这些个人由 id 列标识)。由于文件在某些时候必须以不同方式处理,因此日期时间列的格式在唯一 id 块之间不同 - 即一些单元格的格式为“%Y-%m-%d %H:%M:%S”和有些格式为“%d/%m/%Y %H:%M:%S”,尽管当我打开 csv 文件时它们看起来都是两种格式中的第二种。
我想加载数据并按唯一 ID 值拆分数据,然后根据日期时间列对其进行一系列其他操作。不幸的是,无论我尝试做什么,数据都不会被强制转换为单一类型的日期时间格式。我尝试重新格式化原始 csv 文件中的列,或者加载数据并将其重新分类为具有单一格式的 POSIXct 对象,但是当我这样做时,那些 id 块采用我没有使用 POSIXct 命令指定的格式 return 作为 NA(很明显!)。我还尝试将数据取消分类为数字格式。我尝试的任何方法似乎都不起作用,而且我的数据框太大,无法分别通过每个 id 块!必须有办法做到这一点,而且必须简单!请有人把我从痛苦中解救出来!非常感谢。
示例数据:
> dput(t)
row_id datetime id
1 165656 09/02/2017 15:50:55 1
2 165657 09/02/2017 15:51:25 1
3 165658 09/02/2017 15:51:55 1
4 165659 09/02/2017 15:52:25 1
5 165660 09/02/2017 15:52:55 1
6 165661 2017-02-09 15:53:25 2
7 165662 2017-02-09 15:53:55 2
8 165663 2017-02-09 15:54:25 2
9 165664 2017-02-09 15:54:55 2
我已经尝试了以下两种日期时间格式(这两种格式都只适用于其中一种):
>t$datetime = as.POSIXct(strptime(t$datetime, format="%Y-%m-%d %H:%M:%S"), tz="UTC")
>t$datetime
[1] NA NA NA
[4] NA NA "2017-02-09 15:53:25 UTC"
[7] "2017-02-09 15:53:55 UTC" "2017-02-09 15:54:25 UTC" "2017-02-09 15:54:55 UTC"
>t$datetime = unclass(as.POSIXct(strptime(t$datetime, "%Y-%m-%d %H:%M:%S")))
您可以使用 ifelse
结合 grepl
在调用 as.POSIXct
:
之前检查特定的日期格式掩码
t$dt <- ifelse(grepl("\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}", t$datetime),
as.POSIXct(strptime(t$datetime, "%d/%m/%Y %H:%M:%S")),
as.POSIXct(strptime(t$datetime, "%Y-%m-%d %H:%M:%S")))
这假设您只有两种日期格式。如果可能存在或更多,我们将不得不更改上述解决方案以将其考虑在内。
这里有一些示例数据可以证明这可以工作:
t <- data.frame(datetime=c("09/02/2017 15:50:55", "2017-02-09 15:50:55"))
t$dt <- ifelse(grepl("\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}", t$datetime),
as.POSIXct(strptime(t$datetime, "%d/%m/%Y %H:%M:%S")),
as.POSIXct(strptime(t$datetime, "%Y-%m-%d %H:%M:%S")))
t
datetime dt
1 09/02/2017 15:50:55 1486651855 <-- same values for dt, as expected
2 2017-02-09 15:50:55 1486651855
我们可以使用 lubridate
中的 parse_date_time
并指定数据可以采用的各种格式。
library(lubridate)
df$datetime <- parse_date_time(df$datetime,c("%d/%m/%Y %T", "%Y-%m-%d %T"))
df$datetime
#[1] "2017-02-09 15:50:55 UTC" "2017-02-09 15:51:25 UTC" "2017-02-09 15:51:55 UTC"
#[4] "2017-02-09 15:52:25 UTC" "2017-02-09 15:52:55 UTC" "2017-02-09 15:53:25 UTC"
#[7] "2017-02-09 15:53:55 UTC" "2017-02-09 15:54:25 UTC" "2017-02-09 15:54:55 UTC"
class(df$datetime)
#[1] "POSIXct" "POSIXt"
数据
df <- structure(list(row_id = structure(1:9, .Label = c("1 165656",
"2 165657", "3 165658", "4 165659", "5 165660", "6 165661", "7 165662",
"8 165663", "9 165664"), class = "factor"), datetime = structure(1:9,
.Label = c("09/02/2017 15:50:55", "09/02/2017 15:51:25", "09/02/2017 15:51:55",
"09/02/2017 15:52:25", "09/02/2017 15:52:55", "2017-02-09 15:53:25",
"2017-02-09 15:53:55", "2017-02-09 15:54:25", "2017-02-09 15:54:55"),
class = "factor"), id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L)),
class = "data.frame", row.names = c(NA, -9L))
这似乎是一个愚蠢的问题,但它让我花了好几天的时间首先确定问题是什么,现在试图解决它!
我有一个数据框,其中有一列填满了日期时间。这个数据框是一系列不同处理步骤的产物,这些步骤应用于一系列单独的文件,这些文件在某个时候合并为一个文件(这些个人由 id 列标识)。由于文件在某些时候必须以不同方式处理,因此日期时间列的格式在唯一 id 块之间不同 - 即一些单元格的格式为“%Y-%m-%d %H:%M:%S”和有些格式为“%d/%m/%Y %H:%M:%S”,尽管当我打开 csv 文件时它们看起来都是两种格式中的第二种。
我想加载数据并按唯一 ID 值拆分数据,然后根据日期时间列对其进行一系列其他操作。不幸的是,无论我尝试做什么,数据都不会被强制转换为单一类型的日期时间格式。我尝试重新格式化原始 csv 文件中的列,或者加载数据并将其重新分类为具有单一格式的 POSIXct 对象,但是当我这样做时,那些 id 块采用我没有使用 POSIXct 命令指定的格式 return 作为 NA(很明显!)。我还尝试将数据取消分类为数字格式。我尝试的任何方法似乎都不起作用,而且我的数据框太大,无法分别通过每个 id 块!必须有办法做到这一点,而且必须简单!请有人把我从痛苦中解救出来!非常感谢。
示例数据:
> dput(t)
row_id datetime id
1 165656 09/02/2017 15:50:55 1
2 165657 09/02/2017 15:51:25 1
3 165658 09/02/2017 15:51:55 1
4 165659 09/02/2017 15:52:25 1
5 165660 09/02/2017 15:52:55 1
6 165661 2017-02-09 15:53:25 2
7 165662 2017-02-09 15:53:55 2
8 165663 2017-02-09 15:54:25 2
9 165664 2017-02-09 15:54:55 2
我已经尝试了以下两种日期时间格式(这两种格式都只适用于其中一种):
>t$datetime = as.POSIXct(strptime(t$datetime, format="%Y-%m-%d %H:%M:%S"), tz="UTC")
>t$datetime
[1] NA NA NA
[4] NA NA "2017-02-09 15:53:25 UTC"
[7] "2017-02-09 15:53:55 UTC" "2017-02-09 15:54:25 UTC" "2017-02-09 15:54:55 UTC"
>t$datetime = unclass(as.POSIXct(strptime(t$datetime, "%Y-%m-%d %H:%M:%S")))
您可以使用 ifelse
结合 grepl
在调用 as.POSIXct
:
t$dt <- ifelse(grepl("\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}", t$datetime),
as.POSIXct(strptime(t$datetime, "%d/%m/%Y %H:%M:%S")),
as.POSIXct(strptime(t$datetime, "%Y-%m-%d %H:%M:%S")))
这假设您只有两种日期格式。如果可能存在或更多,我们将不得不更改上述解决方案以将其考虑在内。
这里有一些示例数据可以证明这可以工作:
t <- data.frame(datetime=c("09/02/2017 15:50:55", "2017-02-09 15:50:55"))
t$dt <- ifelse(grepl("\d{2}/\d{2}/\d{4} \d{2}:\d{2}:\d{2}", t$datetime),
as.POSIXct(strptime(t$datetime, "%d/%m/%Y %H:%M:%S")),
as.POSIXct(strptime(t$datetime, "%Y-%m-%d %H:%M:%S")))
t
datetime dt
1 09/02/2017 15:50:55 1486651855 <-- same values for dt, as expected
2 2017-02-09 15:50:55 1486651855
我们可以使用 lubridate
中的 parse_date_time
并指定数据可以采用的各种格式。
library(lubridate)
df$datetime <- parse_date_time(df$datetime,c("%d/%m/%Y %T", "%Y-%m-%d %T"))
df$datetime
#[1] "2017-02-09 15:50:55 UTC" "2017-02-09 15:51:25 UTC" "2017-02-09 15:51:55 UTC"
#[4] "2017-02-09 15:52:25 UTC" "2017-02-09 15:52:55 UTC" "2017-02-09 15:53:25 UTC"
#[7] "2017-02-09 15:53:55 UTC" "2017-02-09 15:54:25 UTC" "2017-02-09 15:54:55 UTC"
class(df$datetime)
#[1] "POSIXct" "POSIXt"
数据
df <- structure(list(row_id = structure(1:9, .Label = c("1 165656",
"2 165657", "3 165658", "4 165659", "5 165660", "6 165661", "7 165662",
"8 165663", "9 165664"), class = "factor"), datetime = structure(1:9,
.Label = c("09/02/2017 15:50:55", "09/02/2017 15:51:25", "09/02/2017 15:51:55",
"09/02/2017 15:52:25", "09/02/2017 15:52:55", "2017-02-09 15:53:25",
"2017-02-09 15:53:55", "2017-02-09 15:54:25", "2017-02-09 15:54:55"),
class = "factor"), id = c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L)),
class = "data.frame", row.names = c(NA, -9L))