¿Hay un método/fórmula estándar/común para calcular el número de meses entre dos fechas en R?Número de meses entre dos fechas
Busco algo que es similar a MathWorks months function
¿Hay un método/fórmula estándar/común para calcular el número de meses entre dos fechas en R?Número de meses entre dos fechas
Busco algo que es similar a MathWorks months function
estaba a punto de decir que es simple, pero difftime()
se detiene en las semanas. Que extraño.
Así que una respuesta posible sería la de cortar algo:
# 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>
parece correcto. Uno podría envolver esto en una estructura de clase simple. O dejarlo como un truco :)
Editar: parece también para trabajar con sus ejemplos de los 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>
añadido la indicación EndOfMonth
se deja como ejercicio para el lector :)
Editar 2: Tal vez difftime
lo omite, ya que no hay una manera confiable de expresar la diferencia de fracciones que sería consistente con el comportamiento difftime
para otras unidades.
Gracias, Dirk. Eso es un truco inteligente. Hablando de unidades, descubrí que esto también funciona .. > as.numeric (as.Date ('2009-10-1') - as.Date ('2009-8-01'), units = 'semanas') > as.numeric (as.Date ('2009-10-1') - as.Date ('2009-8-01'), units = 'days') pero se detiene en 'weeks ' también. – knguyen
Creo que es solo una sobrecarga inteligente del operador - para invocar la misma función 'difftime()'. "No hay almuerzo gratis" como dice el refrán :) –
Hay un mensaje como el suyo en la lista de correo de R-Help (anteriormente mencioné una lista de CRAN).
Aquí the link. Hay dos soluciones sugeridas:
#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
de esta manera:as.Date.numeric <- function(x) structure(floor(x+.001), class = "Date") sapply(d2, function(d2) length(seq(d1, as.Date(d2), by = "month")))-1
Esa sería la lista de correo de R-Help. CRAN es un repositorio de paquetes. – Sharpie
una función simple ...
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)
}
Ejemplo ...
>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
Para mí tiene sentido pensar en este problema como simplemente restando dos fechas, y desde minuend − subtrahend = difference
(wikipedia), puse la fecha posterior primero en la lista de parámetros.
Tenga en cuenta que funciona bien para las fechas anteriores a 1900 a pesar de esas fechas que tiene representaciones internas de años como negativos, gracias a las reglas para restar números negativos ...
> elapsed_months("1791-01-10", "1776-07-01")
[1] 174
Puede haber una manera más sencilla. No es una función, pero es solo una línea.
length(seq(from=date1, to=date2, by='month')) - 1
e.g.
> length(seq(from=Sys.Date(), to=as.Date("2020-12-31"), by='month')) - 1
Produce:
[1] 69
Este calcula el número de meses enteros entre las dos fechas. Quite el -1 si desea incluir el mes/resto actual que no es un mes completo.
Esta es una gran idea, gracias a Dominic – Victor
Esto no siempre da los resultados esperados. 'length (seq (from = as.Date (" 2015-01-31 "), to = as.Date (" 2015-03-31 "), by = 'month')) = 3' Además, 'length (seq (from = as.Date (" 2015-01-31 "), to = as.Date (" 2015-04-30 "), by = 'mes')) = 3' – Octave1
library(lubridate)
Caso 1: la función ingenua
mos<-function (begin, end) {
mos1<-as.period(interval(ymd(begin),ymd(end)))
mos<[email protected]*[email protected]
mos
}
Caso 2: Si es necesario considerar solamente 'Mes', independientemente de 'Día'
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
}
Ejemplo:
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
intervalo (mdy (20150101), mdy (20150228))% /% months (1) Simplemente use el intervalo de función nativo de lubridate. – mtelesha
gracias mtelesha. Sin embargo, en mi negocio, necesito calcular 'recuento de meses' de 2 días a menudo. Por ejemplo, los meses entre 20150131 y 20150201 tienen que ser 1. Entonces, solía hacer la función definida por el usuario 'mob'. ¿Sabes cómo hacer esto usando lubridato? –
Creo que podrías usar month (ymd) - month (ymd). O puede hacer tres columnas una por año, mes y día. – mtelesha
Creo que esta es una respuesta más cercana a la pregunta preguntó en términos de la paridad con la función de MathWorks
MathWorks función meses
MyMonths = months(StartDate, EndDate, EndMonthFlag)
Mi código R
library(lubridate)
interval(mdy(10012015), today()) %/% months(1)
de salida (como cuando el código se ejecuta en abril de 2016)
[1] 6
Lubridat e [paquete] proporciona herramientas que facilitan el análisis y la manipulación de las fechas. Estas herramientas se agrupan a continuación por un propósito común. Se puede encontrar más información sobre cada función en su documentación de ayuda.
intervalo {lubridate} crea un objeto Interval-class con las fechas de inicio y finalización especificadas. Si la fecha de inicio ocurre antes de la fecha de finalización, el intervalo será positivo. De lo contrario, será negativo
hoy {lubridate} La fecha actual
meses{base} Extraer el mes Estas son funciones genéricas: los métodos de las clases de fecha y hora internas están documentadas aquí.
% /% {de base} indica división entera AKA (x% /% y) (hasta error de redondeo)
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)
Diferencia en meses = 12 * diferencia en años + diferencia en meses.
siguiente puede necesitar corregirse utilizando
ifelse
condición de las sustracciones mes
Ver también: http://stackoverflow.com/a/19687995/59087 –