64

ある日付に月を追加しようとしています。しかし、これまでのところ、それはまっすぐな方法では不可能です。以下は私が試したものです。

d <- as.Date("2004-01-31")
d + 60
# [1] "2004-03-31"

月が重ならないため、追加しても役に立ちません。

seq(as.Date("2004-01-31"), by = "month", length = 2) 
# [1] "2004-01-31" "2004-03-02"

上記はうまくいくかもしれませんが、やはり簡単ではありません。また、以下のような問題がある日付に30日か何かを追加します

seq(as.Date("2004-01-31"), by = "month", length = 10) 
#  [1] "2004-01-31" "2004-03-02" "2004-03-31" "2004-05-01" "2004-05-31" "2004-07-01" "2004-07-31" "2004-08-31" "2004-10-01" "2004-10-31"

上記では、最初の2つの日付について、月は変更されていません。

また、次のアプローチも1か月間は失敗しましたが、1年間は成功しました

d <- as.POSIXlt(as.Date("2010-01-01"))
d$year <- d$year +1
d
# [1] "2011-01-01 UTC"
d <- as.POSIXlt(as.Date("2010-01-01"))
d$month <- d$month +1
d

エラーformat.POSIXlt(x, usetz = TRUE):無効な'x'引数

これを行うための正しい方法は何ですか?

4

8 に答える 8

142

%m+%lubridate の関数は、新しい月の最終日を超えることなく 1 か月を追加します。

library(lubridate)
(d <- ymd("2012-01-31"))
 1 parsed with %Y-%m-%d
[1] "2012-01-31 UTC"
d %m+% months(1)
[1] "2012-02-29 UTC"
于 2013-01-06T12:53:46.803 に答える
60

「日付に月を追加する」と言うとあいまいです。

ということですか

  1. 30日追加?
  2. 日付の月の部分を 1 増やしますか?

どちらの場合も、単純な追加のパッケージ全体は少し誇張されているようです。

もちろん、最初の点については、単純な+演算子で次のことができます。

d=as.Date('2010-01-01') 
d + 30 
#[1] "2010-01-31"

2番目については、それと同じくらい単純な(そしてより一般的なスコープで)1行の関数を作成するだけです:

add.months= function(date,n) seq(date, by = paste (n, "months"), length = 2)[2]

負を含む任意の月で使用できます。

add.months(d, 3)
#[1] "2010-04-01"
add.months(d, -3)
#[1] "2009-10-01"

もちろん、単一の月のみを頻繁に追加する場合は、次のようにします。

add.month=function(date) add.months(date,1)
add.month(d)
#[1] "2010-02-01"

1 月 31 日に 1 か月足すと、2 月 31 日は意味がないので、足りない 3 日を翌月の 3 月に足すのが最善の方法です。だから正しく:

add.month(as.Date("2010-01-31"))
#[1] "2010-03-03"

非常に特別な理由で、月の最後の利用可能な日に上限を設定する必要がある場合は、少し長くなります。

add.months.ceil=function (date, n){

  #no ceiling
  nC=add.months(date, n)

  #ceiling
  day(date)=01
  C=add.months(date, n+1)-1

  #use ceiling in case of overlapping
  if(nC>C) return(C)
  return(nC)
}

いつものように、1 か月バージョンを追加できます。

add.month.ceil=function(date) add.months.ceil(date,1)    

そう:

  d=as.Date('2010-01-31')
  add.month.ceil(d)
  #[1] "2010-02-28"
  d=as.Date('2010-01-21')
  add.month.ceil(d)
  #[1] "2010-02-21"

そしてデクリメントで:

  d=as.Date('2010-03-31')
  add.months.ceil(d, -1)
  #[1] "2010-02-28"
  d=as.Date('2010-03-21')
  add.months.ceil(d, -1)
  #[1] "2010-02-21"

さらに、スカラーまたはベクトルのソリューションに興味があるかどうかもわかりませんでした。後者については:

add.months.v= function(date,n) as.Date(sapply(date, add.months, n), origin="1970-01-01")

注:*applyファミリはクラス データを破壊するため、再構築する必要があります。ベクターバージョンは以下をもたらします:

d=c(as.Date('2010/01/01'), as.Date('2010/01/31'))
add.months.v(d,1)
[1] "2010-02-01" "2010-03-03"

気に入っていただければ幸いです))

于 2013-03-09T23:29:22.853 に答える
38

Vanilla R には単純な difftime クラスがありますが、Lubridate CRANパッケージを使用すると、要求どおりに実行できます。

require(lubridate)
d <- ymd(as.Date('2004-01-01')) %m+% months(1)
d
[1] "2004-02-01"

それが役立つことを願っています。

于 2013-01-05T07:38:34.683 に答える
7

"mondate"は、追加すると日ではなく月が追加されることを"Date"除いて、といくらか似ています。nnn

> library(mondate)
> d <- as.Date("2004-01-31")
> as.mondate(d) + 1
mondate: timeunits="months"
[1] 2004-02-29
于 2013-03-10T01:37:36.997 に答える
5

これは、パッケージをインストールする必要がない機能です。Dateオブジェクト (または にcharacter変換できる) を指定すると、日を変更せずにその日付に月がDate追加されます(到着した月に十分な日数がない場合を除きます。デフォルトは、返された月の最終日です)。読んでも意味が分からない場合に備えて、以下にいくつかの例を示します。n

関数定義

addMonth <- function(date, n = 1){
  if (n == 0){return(date)}
  if (n %% 1 != 0){stop("Input Error: argument 'n' must be an integer.")}

  # Check to make sure we have a standard Date format
  if (class(date) == "character"){date = as.Date(date)}

  # Turn the year, month, and day into numbers so we can play with them
  y = as.numeric(substr(as.character(date),1,4))
  m = as.numeric(substr(as.character(date),6,7))
  d = as.numeric(substr(as.character(date),9,10))

  # Run through the computation
  i = 0
  # Adding months
  if (n > 0){
    while (i < n){
      m = m + 1
      if (m == 13){
        m = 1
        y = y + 1
      }
      i = i + 1
    }
  }
  # Subtracting months
  else if (n < 0){
    while (i > n){
      m = m - 1
      if (m == 0){
        m = 12
        y = y - 1
      }
      i = i - 1
    }
  }

  # If past 28th day in base month, make adjustments for February
  if (d > 28 & m == 2){
      # If it's a leap year, return the 29th day
      if ((y %% 4 == 0 & y %% 100 != 0) | y %% 400 == 0){d = 29}
      # Otherwise, return the 28th day
      else{d = 28}
    }
  # If 31st day in base month but only 30 days in end month, return 30th day
  else if (d == 31){if (m %in% c(1, 3, 5, 7, 8, 10, 12) == FALSE){d = 30}}

  # Turn year, month, and day into strings and put them together to make a Date
  y = as.character(y)

  # If month is single digit, add a leading 0, otherwise leave it alone
  if (m < 10){m = paste('0', as.character(m), sep = '')}
  else{m = as.character(m)}

  # If day is single digit, add a leading 0, otherwise leave it alone
  if (d < 10){d = paste('0', as.character(d), sep = '')}
  else{d = as.character(d)}

  # Put them together and convert return the result as a Date
  return(as.Date(paste(y,'-',m,'-',d, sep = '')))
}

いくつかの例

月の追加

> addMonth('2014-01-31', n = 1)
[1] "2014-02-28"  # February, non-leap year
> addMonth('2014-01-31', n = 5)
[1] "2014-06-30"  # June only has 30 days, so day of month dropped to 30
> addMonth('2014-01-31', n = 24)
[1] "2016-01-31"  # Increments years when n is a multiple of 12 
> addMonth('2014-01-31', n = 25)
[1] "2016-02-29"  # February, leap year

月の引き算

> addMonth('2014-01-31', n = -1)
[1] "2013-12-31"
> addMonth('2014-01-31', n = -7)
[1] "2013-06-30"
> addMonth('2014-01-31', n = -12)
[1] "2013-01-31"
> addMonth('2014-01-31', n = -23)
[1] "2012-02-29"
于 2014-07-29T22:06:11.623 に答える
1

私はアントニオの考えを特定の機能に変えました:

library(DescTools)

> AddMonths(as.Date('2004-01-01'), 1)
[1] "2004-02-01"

> AddMonths(as.Date('2004-01-31'), 1)
[1] "2004-02-29"

> AddMonths(as.Date('2004-03-30'), -1)
[1] "2004-02-29"
于 2015-04-29T22:27:13.620 に答える