Esiste un metodo/formula standard/comune per calcolare il numero di mesi tra due date in R?Numero di mesi tra due date
sto cercando qualcosa che è simile a MathWorks months function
Esiste un metodo/formula standard/comune per calcolare il numero di mesi tra due date in R?Numero di mesi tra due date
sto cercando qualcosa che è simile a MathWorks months function
Stavo per dire che è semplice, ma si ferma a difftime()
settimane. Che strano.
Quindi una possibile risposta potrebbe essere quella di incidere qualcosa:
# turn a date into a 'monthnumber' relative to an origin
R> monnb <- function(d) { lt <- as.POSIXlt(as.Date(d, origin="1900-01-01")); \
lt$year*12 + lt$mon }
# compute a month difference as a difference between two monnb's
R> mondf <- function(d1, d2) { monnb(d2) - monnb(d1) }
# take it for a spin
R> mondf(as.Date("2008-01-01"), Sys.Date())
[1] 24
R>
sembra sul punto giusto. Uno potrebbe avvolgere questo in una semplice struttura di classe. O lasciarlo come un hack :)
Edit: sembra anche lavorare con i tuoi esempi di The MathWorks:
R> mondf("2000-05-31", "2000-06-30")
[1] 1
R> mondf(c("2002-03-31", "2002-04-30", "2002-05-31"), "2002-06-30")
[1] 3 2 1
R>
Aggiunta la bandiera EndOfMonth
viene lasciato come esercizio per il lettore :)
Modifica 2: Forse difftime
lascia fuori perché non esiste un modo affidabile per esprimere la differenza frazionale che sarebbe coerente con il comportamento difftime
per le altre unità.
Grazie, Dirk. Questo è un trucco intelligente. Parlando di unità, ho scoperto che questo funziona anche .. > as.numeric (as.Date ('2009-10-1') - as.Date ('2009-8-01'), units = 'settimane') > as.numeric (as.Date ('2009-10-1') - as.Date ('2009-8-01'), units = 'days') ma si ferma a 'settimane ' anche. – knguyen
Penso che sia solo un intelligente sovraccarico dell'operatore - per invocare la stessa funzione 'difftime()'. "No Free Lunch" come dice il proverbio :) –
C'è un messaggio proprio come il tuo nella mailing list di R-Help (in precedenza ho menzionato un elenco CRAN).
Qui the link. Ci sono due soluzioni suggerite:
#test data d1 <- as.Date("01 March 1950", "%d %B %Y") d2 <- as.Date(c("01 April 1955", "01 July 1980"), "%d %B %Y") # calculation round((d2 - d1)/(365.25/12))
seq.Dates
in questo modo:as.Date.numeric <- function(x) structure(floor(x+.001), class = "Date") sapply(d2, function(d2) length(seq(d1, as.Date(d2), by = "month")))-1
Questa sarebbe la mailing list di R-Help. CRAN è un repository di pacchetti. – Sharpie
una semplice funzione ...
elapsed_months <- function(end_date, start_date) {
ed <- as.POSIXlt(end_date)
sd <- as.POSIXlt(start_date)
12 * (ed$year - sd$year) + (ed$mon - sd$mon)
}
Esempio ...
>Sys.time()
[1] "2014-10-29 15:45:44 CDT"
>elapsed_months(Sys.time(), as.Date("2012-07-15"))
[1] 27
>elapsed_months("2002-06-30", c("2002-03-31", "2002-04-30", "2002-05-31"))
[1] 3 2 1
Per me ha senso pensare a questo problema come semplicemente sottraendo due date, e dal minuend − subtrahend = difference
(wikipedia), ho inserito la data successiva prima nell'elenco dei parametri.
Si noti che tutto funziona bene per le date che precedono 1900 nonostante quelle date avendo rappresentazioni interne dell'anno come negativo, grazie alle regole per sottrarre i numeri negativi ...
> elapsed_months("1791-01-10", "1776-07-01")
[1] 174
Ci può essere un modo più semplice. Non è una funzione ma è solo una riga.
length(seq(from=date1, to=date2, by='month')) - 1
, ad es.
> length(seq(from=Sys.Date(), to=as.Date("2020-12-31"), by='month')) - 1
produce:
[1] 69
Questo calcola il numero di mesi interi tra le due date. Rimuovi il -1 se desideri includere il mese/resto corrente che non è un mese intero.
Questa è una grande idea, grazie Dominic – Victor
Questo non sempre dà risultati attesi. lunghezza '(seq (da = as.Date (" 2015-01-31 "), a = as.Date (" 2015-03-31 "), da = 'month')) = 3' Inoltre, lunghezza '(seq (da = as.Date (" 2015-01-31 "), a = as.Date (" 2015-04-30 "), da = 'month')) = 3' – Octave1
library(lubridate)
case1: funzione ingenuo
mos<-function (begin, end) {
mos1<-as.period(interval(ymd(begin),ymd(end)))
mos<[email protected]*[email protected]
mos
}
case2: se avete bisogno di prendere in considerazione solo 'Mese' a prescindere 'Day'
mob<-function (begin, end) {
begin<-paste(substr(begin,1,6),"01",sep="")
end<-paste(substr(end,1,6),"01",sep="")
mob1<-as.period(interval(ymd(begin),ymd(end)))
mob<[email protected]*[email protected]
mob
}
Esempio:
mos(20150101,20150228) # 1
mos(20150131,20150228) # 0
# you can use "20150101" instead of 20150101
mob(20150131,20150228) # 1
mob(20150131,20150228) # 1
# you can use a format of "20150101", 20150101, 201501
intervallo (mdy (20150101), mdy (20150228))% /% months (1) Basta usare l'intervallo di funzione nativa del lubridato. – mtelesha
grazie mtelesha. Tuttavia, nella mia azienda, ho bisogno di calcolare "conteggio mensile" di 2 giorni spesso. Ad esempio, i mesi tra 20150131 e 20150201 devono essere 1. Quindi, ho utilizzato la funzione definita dall'utente "mob". Sai come farlo usando il lubridate? –
Penso che potresti usare il mese (ymd) - month (ymd). Oppure puoi creare tre colonne una per anno, mese e giorno. – mtelesha
Penso che questa sia una risposta più vicina alla domanda ha chiesto in termini di parità con funzione di MathWorks
MathWorks mesi funzione
MyMonths = months(StartDate, EndDate, EndMonthFlag)
Il mio codice R
library(lubridate)
interval(mdy(10012015), today()) %/% months(1)
uscita (come quando il codice è stato eseguito nel mese di aprile 2016)
[1] 6
Lubridat e [pacchetto] fornisce strumenti che semplificano l'analisi e la modifica delle date. Questi strumenti sono raggruppati sotto per uno scopo comune. Ulteriori informazioni su ciascuna funzione sono disponibili nella documentazione della guida.
intervallo {lubridate} crea un oggetto di classe Interval con le date di inizio e fine specificate. Se la data di inizio si verifica prima della data di fine, l'intervallo sarà positivo. In caso contrario, sarà negativo
oggi {lubridate} La data corrente
mesi{base} Estrarre il mese Queste sono funzioni generiche: i metodi per le classi data-ora interni sono documentate Qui.
% /% {basamento} indica la divisione intera AKA (x% /% y) (fino a errore di arrotondamento)
library(lubridate)
date1 = "1 April 1977"
date2 = "7 July 2017"
date1 = dmy(date1)
date2 = dmy(date2)
number_of_months = (year(date1) - year(date2)) * 12 + month(date1) - month(date2)
Differenza di mesi = 12 * differenza di anni + differenza in mesi
In seguito potrebbe essere necessario essere corretta mediante
ifelse
condizioni per le sottrazioni mese
Vedi anche: http://stackoverflow.com/a/19687995/59087 –