webentwicklung-frage-antwort-db.com.de

Fügen Sie einem Datum einen Monat hinzu

Ich versuche, einem Datum, das ich habe, einen Monat hinzuzufügen. Aber dann ist es noch nicht direkt möglich. Folgendes habe ich versucht.

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

Das Hinzufügen hilft nicht, da sich der Monat nicht überschneidet.

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

Oben könnte funktionieren, aber wieder ist es nicht einfach. Außerdem werden dem Datum 30 Tage oder so etwas hinzugefügt, was Probleme wie die folgenden hat

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"

In den ersten beiden oben genannten Daten hat sich der Monat nicht geändert.

Der folgende Ansatz schlug ebenfalls monatelang fehl, war jedoch jahrelang erfolgreich

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

Fehler in format.POSIXlt(x, usetz = TRUE): ungültiges 'x' Argument

Was ist die richtige Methode, um dies zu tun?

52
Vineeth Mohan

Vanilla R hat eine naive Zeitklasse, aber mit dem Paket Lubridate CRAN können Sie tun, wonach Sie fragen:

require(lubridate)
d <- as.Date('2004-01-01')
month(d) <- month(d) + 1
day(d) <- days_in_month(d)
d
[1] "2004-02-29"

Hoffentlich hilft das.

24
hd1

Funktion %m+% von lubridate fügt einen Monat hinzu, ohne den letzten Tag des neuen Monats zu überschreiten.

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"
104
Wojciech Sobala

Es ist mehrdeutig, wenn Sie "einem Datum einen Monat hinzufügen" sagen.

Meinst du

  1. 30 Tage hinzufügen?
  2. erhöhen Sie den Monatsteil des Datums um 1?

In beiden Fällen erscheint ein ganzes Paket für eine einfache Addition etwas übertrieben.

Für den ersten Punkt ist natürlich das einfache + Operator erledigt:

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

Was die zweite betrifft, würde ich einfach eine einzeilige Funktion erstellen (und mit einem allgemeineren Geltungsbereich):

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

Sie können es mit beliebigen Monaten verwenden, einschließlich negativ:

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

Natürlich, wenn Sie nur und oft einen einzelnen Monat hinzufügen möchten:

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

Wenn Sie den 31. Januar um einen Monat verlängern, da der 31. Februar bedeutungslos ist, sollten Sie die fehlenden 3 Tage zum folgenden Monat, dem März, addieren, um die Aufgabe zu erledigen. Also richtig:

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

Falls Sie aus einem ganz besonderen Grund eine Obergrenze für den letzten verfügbaren Tag des Monats festlegen müssen, ist diese etwas länger:

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)
}

Wie üblich können Sie eine einmonatige Version hinzufügen:

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

So:

  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"

Und mit Dekrementen:

  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"

Außerdem haben Sie nicht gesagt, ob Sie sich für eine Skalar- oder Vektorlösung interessieren. Letzteres:

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

Hinweis: *apply Familie zerstört die Klassendaten, deshalb muss sie neu erstellt werden. Die Vektorversion bringt:

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

Hoffe es hat euch gefallen))

53
antonio

"mondate" ist etwas ähnlich zu "Date" mit der Ausnahme, dass durch Hinzufügen von nn Monate anstelle von n Tagen hinzugefügt werden:

> library(mondate)
> d <- as.Date("2004-01-31")
> as.mondate(d) + 1
mondate: timeunits="months"
[1] 2004-02-29
7
G. Grothendieck

Der einfachste Weg ist die Konvertierung von Date in das POSIXlt-Format. Führen Sie dann die arithmetische Operation wie folgt aus:

date_1m_fwd     <- as.POSIXlt("2010-01-01")
date_1m_fwd$mon <- date_1m_fwd$mon +1

Außerdem wird das POSIXlt-Format leider nicht unterstützt, wenn Sie sich mit Datumsspalten in data.table befassen möchten.

Trotzdem können Sie den Monat hinzufügen, indem Sie die grundlegenden R-Codes wie folgt verwenden:

library(data.table)  
dt <- as.data.table(seq(as.Date("2010-01-01"), length.out=5, by="month"))  
dt[,shifted_month:=tail(seq(V1[1], length.out=length(V1)+3, by="month"),length(V1))]

Ich hoffe es hilft.

6
Steven Chau

Hier ist eine Funktion, für die keine Pakete installiert werden müssen. Sie geben ihm ein Date -Objekt (oder ein character, das er in ein Date konvertieren kann) und fügt diesem Datum n Monate hinzu ohne den Tag des Monats zu ändern ( es sei denn der Monat, auf dem Sie landen, enthält nicht genügend Tage. In diesem Fall ist die Standardeinstellung aktiviert bis zum letzten Tag des zurückgegebenen Monats). Nur für den Fall, dass es keinen Sinn macht, es zu lesen, gibt es einige Beispiele unten.

Funktionsdefinition

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 = '')))
}

Einige Beispiele

Hinzufügen von Monaten

> 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

Monate werden abgezogen

> 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"
5
Jacob Amos
addedMonth <- seq(as.Date('2004-01-01'), length=2, by='1 month')[2]
addedQuarter <- seq(as.Date('2004-01-01'), length=2, by='1 quarter')[2]
3
Tung Nguyen

Ich habe Antonios Gedanken in eine bestimmte Funktion verwandelt:

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"
1
Andri Signorell