2016-04-07 12 views
5

最初の日付を指定すると、毎月の間隔で日付のシーケンスを生成し、すべての要素が同じ日が無効な日付を返す場合は、最初の日付またはその月の最後の日。毎月の日付のシーケンスが同じ日、または無効の場合の月の最終日になるようにする

かなり標準的な音ですか?

difftimeを使用することはできません。ここdifftimeのヘルプファイルが言うことだ。彼らは一定の 長さのものではないような「ヶ月」など

単位はできません。月、四半期、または年の間隔を作成するには、seq.Date またはseq.POSIXtを使用します。

しかし、その後、私がいることを見つけるseq.POSIXtのヘルプファイルを見ている:「月」を使用して

初日変えずに月進み:これは月の無効な日になり 場合、それは翌月に と数えられます:例を見てください。

これはヘルプファイルの例です。

seq(ISOdate(2000,1,31), by = "month", length.out = 4) 
> seq(ISOdate(2000,1,31), by = "month", length.out = 4) 
[1] "2000-01-31 12:00:00 GMT" "2000-03-02 12:00:00 GMT" 
"2000-03-31 12:00:00 GMT" "2000-05-01 12:00:00 GMT" 

だから、最初の日が31日目であることを考えると、これは「フォワードカウント」のでだから、シーケンスが実際にそれらヶ月を飛ばしてしまうなどの2月、4月、上の無効な日付をもたらすと終わるだろう2月29日ではなく、3月2日となります。

私は2000年1月31日に開始する場合は、次のように、私はシーケンスをしたいと思います:

  • 2000年1月31日
  • 2000-02-
  • 2000-03- 31
  • 2000年4月30日
  • ...

そして、それはよhould適切に初期日付が2015年1月31日ですので、もしシーケンスがあるべき、飛躍の年取扱い:

  • 2015年1月31日
  • 2015-02-
  • 2015から03いいえ、-31
  • 2015年4月30日
  • は...

これらの問題を説明するための一例であり、私は事前に初期日付を知りません私はそれについて何かを仮定することができます。当初の日付は月の半ば(2015-01-15)になる可能性があり、その場合はseqが問題ありません。しかし、例のように、seqだけを使用した日付の月末には、問題があるかもしれません(29,30、および31日目)。最初の日付がその月の最後の日であると仮定することはできません。

解決策を見つけようとしています。ここにあるいくつかの質問では、次の月の最初の日を取得することによって、月の最後の日を取得するための "トリック"があり、単純に1を引いています。最初の日を見つけることは "簡単"ですちょうど1日目

あるだから私のソリューションは、これまでのところです:

# Given an initial date for my sequence 
initial_date <- as.Date("2015-01-31") 

# Find the first day of the month 
library(magrittr) # to use pipes and make the code more readable 
firs_day_of_month <- initial_date %>% 
    format("%Y-%m") %>% 
    paste0("-01") %>% 
    as.Date() 

# Generate a sequence from initial date, using seq 
# This is the sequence that will have incorrect values in months that would 
# have invalid dates 
given_dat_seq <- seq(initial_date, by = "month", length.out = 4) 

# And then generate an auxiliary sequence for the last day of the month 
# I do this generating a sequence that starts the first day of the 
# same month as initial date and it goes one month further 
# (lenght 5 instead of 4) and substract 1 to all the elements 
last_day_seq <- seq(firs_day_of_month, by = "month", length.out = 5)-1 

# And finally, for each pair of elements, I take the min date of both 
pmin(given_dat_seq, last_day_seq[2:5]) 

それは動作しますが、それは、同時に、ちょっと、ダムハックと複雑です。だから私はそれが気に入らない。そして、最も重要なのは、Rでこれを行う簡単な方法がないとは信じられません。

もっと簡単な解決策を教えてもらえますか? (私はseq(initial_date, "month", 4)と同じくらいシンプルであったはずですが、明らかにそうではありません)。私はそれをgoogledして、SOとRのメーリングリストでここを見ましたが、上記のトリックは別として、私は解決策を見つけることができませんでした。

+0

はできませんでした'seq(as.Date(" 2015-01-31 ")+ 1、length = 4、by =" month ") - 1'を実行するだけです。 – mtoto

+0

いいえ、最初の日付は任意です(この例では、問題を説明するためにJan-31を使用しましたが、私は最初の日付を事前に知らず、必ずしもその月の最終日ではありません)。あなたが言うように、最初の日付が「2015-01-15」である場合、私のシーケンスは、毎月15日に予定されている第16日に常にあります。ありがとう、あなたは私のかなり長い質問ではっきりしていなかったことを私に気づかせました。私はそれを編集します。 – elikesprogramming

答えて

3

最も簡単な解決策は、この正確な問題を解決するlubridateの%m+%です。だから、:

seq_monthly <- function(from,length.out) { 
    return(from %m+% months(c(0:(length.out-1)))) 
} 

出力:

、ここで(C++からブーストDate.timeのライブラリをラップ)RcppBDTを使用して1 lubridateの答えと同様に
> seq_monthly(as.Date("2015-01-31"),length.out=4) 
[1] "2015-01-31" "2015-02-28" "2015-03-31" "2015-04-30" 
3

では

R> dt <- new(bdtDt, 2010, 1, 31); for (i in 1:5) { dt$addMonths(i); print(dt) } 
[1] "2010-02-28" 
[1] "2010-04-30" 
[1] "2010-07-31" 
[1] "2010-11-30" 
[1] "2011-04-30" 
R> dt <- new(bdtDt, 2000, 1, 31); for (i in 1:5) { dt$addMonths(i); print(dt) } 
[1] "2000-02-29" 
[1] "2000-04-30" 
[1] "2000-07-31" 
[1] "2000-11-30" 
[1] "2001-04-30" 
R> 
関連する問題