gpt4 book ai didi

r - 有效地转换data.table中的日期列

转载 作者:行者123 更新时间:2023-12-04 05:36:31 26 4
gpt4 key购买 nike

我有一个大型数据集,其中许多列包含两种不同格式的日期:

"1996-01-04" "1996-01-05" "1996-01-08" "1996-01-09" "1996-01-10" "1996-01-11"


"02/01/1996" "03/01/1996" "04/01/1996" "05/01/1996" "08/01/1996" "09/01/1996"

在这两种情况下,class()均为“字符”。由于数据集有很多行(450万行),因此我正在寻找一种有效的data.table转换方法。现在,我使用此自建函数:
convert_to_date <- function(in_array){
tmp <- try(as.Date(in_array, format = "%d/%m/%Y"),TRUE)
if (all(!is.na(tmp)) & class(tmp) != "try-error"){
return(tmp)
} else{
tmp2 <- try(as.Date(in_array),TRUE)
if (all(!is.na(tmp2)) & class(tmp2) != "try-error"){
return(tmp2)
} else{
return(in_array)
}
}
}

然后,通过它我可以转换所需的(data.table DF的)列
DF[,date:=convert_to_date(date)]

但是,这仍然非常慢(每列将近45s)。

有什么办法可以通过data.table方法来优化它吗?到目前为止,我还没有找到更好的方法,因此,我将感谢您提供的任何提示。

附注:为了提高可读性,我已经将该功能“外包”到了另一个文件中,并在我的主例程中提供了它。这会对R中的计算速度产生(负面的)重大影响吗?

最佳答案

根据this benchmark的说法,将标准明确格式(YYYY-MM-DD)的字符日期转换为Date 类的最快方法是使用as.Date(fasttime::fastPOSIXct())
不幸的是,这需要事先测试格式,因为DD/MM/YYYY会误解您的其他格式fasttime::fastPOSIXct()
因此,如果您不想打扰每个日期列的格式,则可以使用anytime::anydate()函数:

# sample data
df <- data.frame(
X1 = c("1996-01-04", "1996-01-05", "1996-01-08", "1996-01-09", "1996-01-10", "1996-01-11"),
X2 = c("02/01/1996", "03/01/1996", "04/01/1996", "05/01/1996", "08/01/1996", "09/01/1996"),
stringsAsFactors = FALSE)

library(data.table)
# convert date columns
date_cols <- c("X1", "X2")
setDT(df)[, (date_cols) := lapply(.SD, anytime::anydate), .SDcols = date_cols]
df
           X1         X2
1: 1996-01-04 1996-02-01
2: 1996-01-05 1996-03-01
3: 1996-01-08 1996-04-01
4: 1996-01-09 1996-05-01
5: 1996-01-10 1996-08-01
6: 1996-01-11 1996-09-01


benchmark timings表明 anytime包提供的便利性和性能之间需要权衡。因此,如果速度至关重要,则没有其他方法可以测试每一列的格式并使用可用于该格式的最快的转换方法。
OP为此使用了 try()函数。下面的解决方案使用正则表达式查找与给定格式匹配的所有列(仅使用行1可以节省时间)。这样做还有一个好处,即相关列的名称是自动确定的,不需要键入。
# enhanced sample data with additional columns
df <- data.frame(
X1 = c("1996-01-04", "1996-01-05", "1996-01-08", "1996-01-09", "1996-01-10", "1996-01-11"),
X2 = c("02/01/1996", "03/01/1996", "04/01/1996", "05/01/1996", "08/01/1996", "09/01/1996"),
X3 = "other data",
X4 = 1:6,
stringsAsFactors = FALSE)

library(data.table)
options(datatable.print.class = TRUE)

# coerce to data.table
setDT(df)[]
# convert date columns in standard unambiguous format YYYY-MM-DD
date_cols1 <- na.omit(names(df)[
df[1, sapply(.SD, stringr::str_detect, pattern = "\\d{4}-\\d{2}-\\d{2}"),]])
# use fasttime package
df[, (date_cols1) := lapply(.SD, function(x) as.Date(fasttime::fastPOSIXct(x))),
.SDcols = date_cols1]
# convert date columns in DD/MM/YYYY format
date_cols2 <- na.omit(names(df)[
df[1, sapply(.SD, stringr::str_detect, pattern = "\\d{2}/\\d{2}/\\d{4}"),]])
# use lubridate package
df[, (date_cols2) := lapply(.SD, lubridate::dmy), .SDcols = date_cols2]
df
           X1         X2         X3    X4
<Date> <Date> <char> <int>
1: 1996-01-04 1996-01-02 other data 1
2: 1996-01-05 1996-01-03 other data 2
3: 1996-01-08 1996-01-04 other data 3
4: 1996-01-09 1996-01-05 other data 4
5: 1996-01-10 1996-01-08 other data 5
6: 1996-01-11 1996-01-09 other data 6

警告
如果其中一个日期列在第一行中确实包含 NA,则该列可能会转义而未转换。为了处理这些情况,需要修改以上代码。

关于r - 有效地转换data.table中的日期列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46078151/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com