2013-08-22 4 views
11

ファイルを読むとき、read.table関数はtype.convertを使用して論理、整数、数値、複合、または係数の列を区別し、それに応じて格納します。は、ファイルをデータフレームに読み込むときに日付列を自動的に検出します。

日付を含む列が自動的に認識され、Dateオブジェクトに解析されるように、日付をミックスに追加したいとします。ほんのわずかの日付形式しか認識されません。ここで

date.formats <- c("%m/%d/%Y", "%Y/%m/%d") 

例です。

fh <- textConnection(

"num char date-format1 date-format2 not-all-dates not-same-formats 
    10  a  1/1/2013 2013/01/01  2013/01/01   1/1/2013 
    20  b  2/1/2013 2013/02/01    a  2013/02/01 
    30  c  3/1/2013   NA    b   3/1/2013" 
) 

そして

dat <- my.read.table(fh, header = TRUE, stringsAsFactors = FALSE, 
        date.formats = date.formats) 
sapply(dat, class) 

の出力は与えるだろう:

num    => numeric 
char    => character 
date-format1  => Date 
date-format2  => Date 
not-all-dates => character 
not-same-formats => character # not a typo: date format must be consistent 

を、私は最初からそれを移動して、実装する前に、さこのようなものは既にパッケージで利用できますか?または、誰かが既にそれに亀裂(または意志)を与えていて、ここでコードを共有しようとしていますか?ありがとうございました。

+0

parse_date_time(...)をラップすることです/ read.csv](http://stackoverflow.com/q/13022299/271616)。 –

+1

関連する、はい、このトピックを研究している人には役に立ちます。私の場合でも、私は日付の列が自動的に検出される必要があります。 – flodel

+0

は「同じ形式」で、「正確な形式」または「ymd」の順序が重要です(同じ列の「2013/01/01」と「2013-01-01」は大丈夫でしょうか?) – mnel

答えて

0

ここで私はすぐに一緒に投げました。あなたがよりフォーマット周りより厳密である日付を解析する方法を知っていれば

my.read.table <- function(..., date.formats = c("%m/%d/%Y", "%Y/%m/%d")) { 
    dat <- read.table(...) 
    for (col.idx in seq_len(ncol(dat))) { 
     x <- dat[, col.idx] 
     if(!is.character(x) | is.factor(x)) next 
     if (all(is.na(x))) next 
     for (f in date.formats) { 
     d <- as.Date(as.character(x), f) 
     if (any(is.na(d[!is.na(x)]))) next 
     dat[, col.idx] <- d   
     } 
    } 
    dat 
} 

dat <- my.read.table(fh, header = TRUE, stringsAsFactors = FALSE) 
as.data.frame(sapply(dat, class)) 

#     sapply(dat, class) 
# num       integer 
# char      character 
# date.format1     Date 
# date.format2     Date 
# not.all.dates    character 
# not.same.formats    Date 

(...​​は、例えば、[OK]解析することを参照)as.Date機能が十分に厳格ではないので、適切に最後の列を処理していませんas.Date(上記の例を参照)、私にお知らせください。

編集:私は必要がありますが、それが機能するためには、私は

if (!identical(x, format(d, f))) next 

を追加することができ、日付が超厳格な構文解析を行うためにすべての私の入力が必要な場合、すなわち01/01/2013なく1/1/2013を先行ゼロを持つようにさかのぼり。それが標準的な方法なら、私はそれで生きることができます。

1

正規表現を試すことができます。

my.read.table <- function(..., date.formats = c("%m/%d/%Y", "%Y/%m/%d")) { 
    require(stringr) 
    formats <- c(
    "%m" = "[0-9]{1,2}", 
    "%d" = "[0-9]{1,2}", 
    "%Y" = "[0-9]{4}" 
    ) 
    dat <- read.table(...) 
    for (col.idx in seq_len(ncol(dat))) { 
     for (format in date.formats) { 
     x <- dat[, col.idx] 
     if(!is.character(x) | is.factor(x)) break 
     if (all(is.na(x))) break 
     x <- as.character(x) 
     # Convert the format into a regular expression 
     for(k in names(formats)) { 
      format <- str_replace_all(format, k, formats[k]) 
     } 
     # Check if it matches on the non-NA elements 
     if(all(str_detect(x, format) | is.na(x))) { 
      dat[, col.idx] <- as.Date(x, format) 
      break 
     } 
     } 
    } 
    dat 
} 

dat <- my.read.table(fh, header = TRUE, stringsAsFactors = FALSE) 
as.data.frame(sapply(dat, class)) 
#     sapply(dat, class) 
# num       integer 
# char      character 
# date.format1     Date 
# date.format2     Date 
# not.all.dates    character 
# not.same.formats   character 
3

あなたは少し厳しいです(とPOSIXlt作成)データをlubridate::parse_date_timeを、使用することができます。

また、既存のNA値をもう少しチェックしました(必要ではないかもしれません)。

例えば

library(lubridate) 
my.read.table <- function(..., date.formats = c("%m/%d/%Y", "%Y/%m/%d")) { 
    dat <- read.table(...) 
    for (col.idx in seq_len(ncol(dat))) { 
    x <- dat[, col.idx] 
    if(!is.character(x) | is.factor(x)) next 
    if (all(is.na(x))) next 
    for (format in date.formats) { 
     complete.x <- !(is.na(x)) 
     d <- as.Date(parse_date_time(as.character(x), format, quiet = TRUE)) 
     d.na <- d[complete.x] 
     if (any(is.na(d.na))) next 
     dat[, col.idx] <- d   
    } 
    } 
    dat 

} 

dat <- my.read.table(fh, stringsAsFactors = FALSE,header=TRUE) 

str(dat) 
'data.frame': 3 obs. of 6 variables: 
$ num    : int 10 20 30 
$ char   : chr "a" "b" "c" 
$ date.format1 : Date, format: "2013-01-01" "2013-02-01" "2013-03-01" 
$ date.format2 : Date, format: "2013-01-01" "2013-02-01" NA 
$ not.all.dates : chr "2013/01/01" "a" "b" 
$ not.same.formats: chr "1/1/2013" "2013/02/01" "3/1/2013" 

代替は[read.tableを中colClasses引数の日付書式を指定関数内options(warn = 2)を使用してに関連するtry文

my.read.table <- function(..., date.formats = c("%m/%d/%Y", "%Y/%m/%d")) { 
    dat <- read.table(...) 
    owarn <-getOption('warn') 
    on.exit(options(warn = owarn)) 
    options(warn = 2) 
    for (col.idx in seq_len(ncol(dat))) { 
    x <- dat[, col.idx] 
    if(!is.character(x) | is.factor(x)) next 
    if (all(is.na(x))) next 
    for (format in date.formats) { 
     d <- try(as.Date(parse_date_time(as.character(x), format)), silent= TRUE) 

     if (inherits(d, 'try-error')) next 
     dat[, col.idx] <- d   
    } 
    } 
    dat 

} 
+0

有望な、今、お試しの音! – flodel

+0

@flodel - 'any(is.na(...)) 'の代わりに' try'を使ってオプションを追加しました。 – mnel

+0

と利点は、日付を解析できないとすぐに終了しますか?全体的に速いですか? – flodel

関連する問題