2014-05-23 42 views

回答

2

使用strsplit將字符串拆分爲「M」。然後將結果年份&與當天的「01」一起粘貼。最後,使用as.Date。向量化,使用sapply

> foo <- c("2005M09","2005M10") 
> as.Date(sapply(strsplit(foo,"M"), 
    function(xx)paste(xx[1],"-",xx[2],"-01",sep=""))) 
[1] "2005-09-01" "2005-10-01" 

如果你喜歡在你的問題的輸出格式,這樣做:

> bar <- as.Date(sapply(strsplit(foo,"M"), 
    function(xx)paste(xx[1],"-",xx[2],"-01",sep=""))) 
> format(bar,format="%d/%m/%Y") 
[1] "01/09/2005" "01/10/2005" 
+0

非常感謝您的幫助Stephan!這是我有史以來第一個關於堆棧溢出的問題,所以請原諒我注意細節......我忘了提及這個字符串是數據框的一部分。這在這種特殊情況下也能起作用嗎? – fitzdrake

+0

我想我已經設法解決了我的問題。我用過strsplit(as。字符(x),「M」)並且完美地工作。再次,謝謝你! – fitzdrake

+0

啊,那麼你的'x'可能是一個開始的因素。我建議下次把'dput(x)'的輸出放到你的問題中,這將幫助我們將這些問題扼殺在萌芽狀態。 –

2

看看在lubridate包,它有很多功能,用於處理日期。一種選擇是貼上類似「D01」,以每個日期,然後使用ymd功能:

> ymd(paste0(c('2005M09','2014M05'), 'D01')) 
[1] "2005-09-01 UTC" "2014-05-01 UTC" 

或拆分的一年,像斯蒂芬月份提出並使用lubridate功能使用那些年月:

> tmp <- strsplit(c('2005M09','2014M05'), 'M') 
> dates <- rep(today(), length(tmp)) 
> year(dates) <- as.numeric(sapply(tmp, `[`, 1)) 
> month(dates) <- as.numeric(sapply(tmp, `[`, 2)) 
> day(dates) <- 1 
> dates 
[1] "2005-09-01" "2014-05-01" 
1

您可以使用as.Date()轉換爲日期,並打印它就像你想要的。看看?strptime看看如何構造format參數的字符串。

txt <- c("2005M09", "2005M10") 
(d <- as.Date(paste0(txt, "01"), format="%YM%m%d")) 
#[1] "2005-09-01" "2005-10-01" 
format(d, "%d/%m/%Y") 
#[1] "01/09/2005" "01/10/2005" 

你也可以使用substr創建一個字符串這是「容易」轉換爲日期。我認爲這兩種解決方案會比使用strsplitsapply

d <- as.Date(paste0(substr(txt, 1, 4), substr(txt, 6, 7), "01"), format="%Y%m%d") 

其實快了不少,忘記轉換爲日期,你可以簡單地substr出你想要什麼,但是你想它粘貼在一起(如果這是所有你想做的事...存儲爲Date小號有日期可能使其他事情變得更容易。)

> paste("01", substr(txt, 6, 7), substr(txt, 1, 4), sep="/") 
[1] "01/09/2005" "01/10/2005" 

或者,這裏有一個正則表達式的解決方案

> sub("(\\d{4})M(\\d{2})", "01/\\2/\\1", txt) 
[1] "01/09/2005" "01/10/2005" 

如果速度是一個問題,這裏是一個標杆

gsee1 <- function(txt) { 
    format(as.Date(paste0(txt, "01"), format="%YM%m%d"), "%d/%m/%Y") 
} 

gsee2 <- function(txt) { 
    format(as.Date(paste0(substr(txt, 1, 4), substr(txt, 6, 7), "01"), 
       format="%Y%m%d"), "%d/%m/%Y") 
} 

gsee3 <- function(txt) { 
    paste("01", substr(txt, 6, 7), substr(txt, 1, 4), sep="/") 
} 

gsee4 <- function(txt) { 
    sub("(\\d{4})M(\\d{2})", "01/\\2/\\1", txt, perl=TRUE) 
} 

gsnow <- function(txt) { 
    tmp <- strsplit(txt, 'M') 
    dates <- rep(today(), length(tmp)) 
    year(dates) <- as.numeric(sapply(tmp, `[`, 1)) 
    month(dates) <- as.numeric(sapply(tmp, `[`, 2)) 
    day(dates) <- 1 
    format(dates, "%d/%m/%Y") 
} 

stephan <- function(txt) { 
    format(as.Date(sapply(strsplit(txt,"M"), 
         function(xx)paste(xx[1],"-",xx[2],"-01",sep=""))), 
     format="%d/%m/%Y") 
} 

identical(gsee1(txt), gsee2(txt)) 
#[1] TRUE 
identical(gsee1(txt), gsee3(txt)) 
#[1] TRUE 
identical(gsee1(txt), gsee4(txt)) 
#[1] TRUE 
identical(gsee1(txt), gsnow(txt)) 
#[1] TRUE 
identical(gsee1(txt), stephan(txt)) 
#[1] TRUE 

結果:

library(rbenchmark) 
# Create a bigger input vector 
txt <- c(outer(1900:2100, sprintf("%02d", 1:12), paste, sep="M")) 
benchmark(gsee1(txt), 
      gsee2(txt), 
      gsee3(txt), 
      gsee4(txt), 
      gsnow(txt), 
      stephan(txt)) 

#   test replications elapsed relative user.self sys.self user.child sys.child 
# 1 gsee1(txt)   100 0.413 3.896  0.412 0.000   0   0 
# 2 gsee2(txt)   100 0.470 4.434  0.468 0.000   0   0 
# 3 gsee3(txt)   100 0.140 1.321  0.140 0.000   0   0 
# 4 gsee4(txt)   100 0.106 1.000  0.104 0.000   0   0 
# 5 gsnow(txt)   100 4.407 41.575  4.400 0.004   0   0 
# 6 stephan(txt)   100 2.526 23.830  2.420 0.100   0   0