将字符串日期转换为数字的快速方法是什么?

时间:2014-01-12 21:31:46

标签: r

我有很多大型csv文件(几MB),有很多数字和时间,所有值都没有引号存储,并用分号分隔。数字用冒号编码,用于十进制分隔符。时间编码为hh:mm:ss。缺少许多值,它们被编码为大小为零的字符串(不是“NA”)。

我需要将表示数字的字符串转换为数字,将时间转换为某些数字表示,以便进行简单的算术运算。 AFAIK R中的默认日期/时间表示非常笨重,我系统上的POSIXct对象长312个字节。

我使用这样的代码:

library(chron) #For chron function
library(plyr)

string2time<-function(f)
{
  if(is.na(f))
  {
    return(NA)
  }
  if(f==''){
    return(NA)
  } 
  n<-as.numeric(f)
  if(is.na(n))
  {
    ans<-n
    try(ans<-chron(times.=f),
        silent=TRUE)
    return(as.numeric(ans))
  }
  return(n)
}

interpreteCSV<-function(filename,parallel)
{
   data<-read.csv2(filename)
   data.fix<-t(laply(data,function(x) {aaply(as.character(x),1,string2time)},.parallel=parallel))
   return(data.fix)
}

问题是该功能似乎非常低效。

我知道,这个函数看起来很笨拙,但它是唯一一个与缺失值一起使用的函数。如果我写了两个函数,也许我可以加快一点:一个用于数字列,另一个用于时间列。但有些东西告诉我,我在这里缺少一些基本的东西,这就是为什么我要求你提供一些灵感。

以下是摘要摘录:

> ?Rprof
> summaryRprof(filename="/tmp/temp/rprof.out")
$by.self
                           self.time self.pct total.time total.pct
".Call"                         0.30    93.75       0.30     93.75
"getIterVal.containeriter"      0.02     6.25       0.02      6.25

$by.total
                           total.time total.pct self.time self.pct
"<Anonymous>"                    0.32    100.00      0.00     0.00
"a_ply"                          0.32    100.00      0.00     0.00
"%dopar%"                        0.32    100.00      0.00     0.00
"l_ply"                          0.32    100.00      0.00     0.00
"prepare.rds.from.csv"           0.32    100.00      0.00     0.00
".Call"                          0.30     93.75      0.30    93.75
"mclapply"                       0.30     93.75      0.00     0.00
"FUN"                            0.16     50.00      0.00     0.00
"lapply"                         0.16     50.00      0.00     0.00
"selectChildren"                 0.16     50.00      0.00     0.00

csv的示例行看起来像那样(不包括标题)。文件中有几千个这样的行:

1;XAD-01;m;wn;18,00;6;7;6;60;;;;15:10:11.8;;2,73;;16,56;;15:10:19.4;;15:10:11.8;;15:10:23.9;;15:10:19.4;;15:10:28.6;;0;;0;;0;;0;;15:10:06.0;;59,70;;15:10:36.6;;-1,47;;617;;0;;3,65;;29,96;;15:10:33.4;;15,97;;15:10:33.4;;4,43;5;12;4;30;8;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

1 个答案:

答案 0 :(得分:1)

我们假设您知道哪些列号需要转换。进一步假设这组列位于名为cols.to,convert

的向量中
cols.to.convert <-  grep( "\\d{1,2}\\:\\d{1,2}\\:\\d{1,2}", dfrm[1,])
cols.to.convert
# [1] 13 19 21 23 25 27 37 41 53 57

dfrm[cols.to.convert]  <- lapply(dfrm[cols.to.convert], as.POSIXct, format="%H:%M:%S")

# all now POSIXct class.
lapply(dfrm[cols.to.convert], class)

请注意,R POSIXct向量将同时包含日期和时间,默认情况下,从仅时间格式转换将返回日期时间与今天的日期:

> dfrm$V57
[1] "2014-01-12 15:10:33 PST"

然后对于NA转换,这应该是相当有效的:

  is.na(dfrm) <- dfrm = =""