r - 提高数据表日期+时间粘贴的性能?

标签 r performance data.table posixct

我不确定我可以在这里问这个问题,让我知道我是否应该在其他地方问这个问题。

我有一个具有 1e6 行的 data.table 具有以下结构:

        V1       V2     V3
1: 03/09/2011 08:05:40 1145.0
2: 03/09/2011 08:06:01 1207.3
3: 03/09/2011 08:06:17 1198.8
4: 03/09/2011 08:06:20 1158.4
5: 03/09/2011 08:06:40 1112.2
6: 03/09/2011 08:06:59 1199.3

我正在使用以下代码将 V1 和 V2 变量转换为唯一的日期时间变量:
 system.time(DT[,`:=`(index= as.POSIXct(paste(V1,V2),
                         format='%d/%m/%Y %H:%M:%S'),
                     V1=NULL,V2=NULL)])

   user  system elapsed 
   47.47    0.16   50.27 

有什么方法可以提高这种转换的性能吗?

这里dput(head(DT)) :
DT <- structure(list(V1 = c("03/09/2011", "03/09/2011", "03/09/2011", 
"03/09/2011", "03/09/2011", "03/09/2011"), V2 = c("08:05:40", 
"08:06:01", "08:06:17", "08:06:20", "08:06:40", "08:06:59"), 
    V3 = c(1145, 1207.3, 1198.8, 1158.4, 1112.2, 1199.3)), .Names = c("V1", 
"V2", "V3"), class = c("data.table", "data.frame"), row.names = c(NA, 
-6L), .internal.selfref = <pointer: 0x00000000002a0788>)

最佳答案

这种方法的运行速度似乎比 OP 快 40 倍,它使用查找表并利用极快的数据表连接。此外,它利用了这样一个事实,虽然日期和时间可能有 1e6 个组合,但最多可以有 86400 个唯一时间,甚至可能有更少的日期。最后,它避免使用 paste(...)共。

library(data.table)
library(stringr)

# create a dataset with 1MM rows
set.seed(1)
x  <- 1000*sample(1:1e5,1e6,replace=T)
dt <- data.table(id=1:1e6,
                 V1=format(as.POSIXct(x,origin="2011-01-01"),"%d/%m/%Y"),
                 V2=format(as.POSIXct(x,origin="2011-01-01"),"%H:%M:%S"),
                 V3=x)
DT <- dt

index.date <- function(dt) {
  # Edit: this change processes only times from the dataset; slightly more efficient
  V2 <- unique(dt$V2)
  dt.time <- data.table(char.time=V2,
                        int.time=as.integer(substr(V2,7,8))+
                          60*(as.integer(substr(V2,4,5))+
                                60*as.integer(substr(V2,1,2))))
  setkey(dt.time,char.time)
  # all dates from dataset
  dt.date <- data.table(char.date=unique(dt$V1), int.date=as.integer(as.POSIXct(unique(dt$V1),format="%d/%m/%Y")))
  setkey(dt.date,char.date)
  # join the dates
  setkey(dt,V1)
  dt <- dt[dt.date]
  # join the times
  setkey(dt,V2)
  dt <- dt[dt.time, nomatch=0]
  # numerical index
  dt[,int.index:=int.date+int.time]
  # POSIX date index
  dt[,index:=as.POSIXct(int.index,origin='1970-01-01')]
  # get back original order
  setkey(dt,id)
  return(dt)
}
# new approach
system.time(dt<-index.date(dt))
#   user  system elapsed 
#   2.26    0.00    2.26 


# original approach
DT <- dt
system.time(DT[,`:=`(index= as.POSIXct(paste(V1,V2),
                                       format='%d/%m/%Y %H:%M:%S'),
                     V1=NULL,V2=NULL)])
#   user  system elapsed 
#  84.33    0.06   84.52 

请注意,性能确实取决于有多少个唯一日期。在测试用例中,有大约 1200 个唯一日期。

编辑 建议以更多 data.table-sugar 语法编写函数并避免使用“$”进行子集化:
index.date <- function(dt,fmt="%d/%m/%Y") {
    dt.time <- data.table(char.time = dt[,unique(V2)],key='char.time')
    dt.time[,int.time :=as.integer(substr(char.time,7,8))+
                                            60*(as.integer(substr(char.time,4,5))+
                                                        60*as.integer(substr(char.time,1,2)))]
    # all dates from dataset
    dt.date <- data.table(char.date = dt[,unique(V1)],key='char.date')
    dt.date[,int.date:=as.integer(as.POSIXct(char.date,format=fmt))]
    # join the dates
    setkey(dt,V1)
    dt <- dt[dt.date]
    # join the times
    setkey(dt,V2)
    dt <- dt[dt.time, nomatch=0]
    # numerical index
    dt[,int.index:=int.date+int.time]
    # POSIX date index
    dt[,index:=as.POSIXct.numeric(int.index,origin='1970-01-01')]
    # remove extra/temporary variables
    dt[,`:=`(int.index=NULL,int.date=NULL,int.time=NULL)]
}

关于r - 提高数据表日期+时间粘贴的性能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20483217/

相关文章:

r - 如何通过重复字符在R中设置列名?

sql-server - R:使用 ODBC 和 SQL Server 读取性能非常慢

performance - 为什么使用 Inline::C 用虚拟函数替换 Perl 的 s///会导致显着变慢?

r - 使用 `data.table` 的 DT[ i , j, by] 时,是否可以事先设置列类型?

r - 如何在 data.table 中选择同时匹配另一个 data.table 中的两个条件的行?

r - 带有 Access DB 的 R 中的 ODBC 是否存在任何语言问题?

R ggplot2堆叠条以错误的顺序填充一个条

c# - 清除文本文件中过多旧数据的高效方法

javascript - 如何调试 Chrome 中的性能异常?

r - 按 id 和 date 合并两个数据框