Existe-t-il une méthode/formule standard/commune pour calculer le nombre de mois entre deux dates en R?
Je recherche quelque chose de similaire à MathWorks months function
J'allais dire que c'est simple, mais difftime()
s'arrête à des semaines. Tellement bizzare.
Donc, une réponse possible serait de pirater quelque chose:
# 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>
Semble à peu près juste. On pourrait intégrer cela dans une structure de classe simple. Ou le laisser comme un bidouillage :)
Edit: semble également fonctionner avec vos exemples de 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>
L'ajout du drapeau EndOfMonth
est laissé au lecteur comme un exercice :)
Edit 2: Peut-être que difftime
l'ignore, car il n'existe aucun moyen fiable d'exprimer une différence fractionnaire compatible avec le comportement de difftime
pour les autres unités.
Une fonction 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)
}
Exemple...
>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
Pour moi, il est logique de penser à ce problème comme une simple soustraction de deux dates et comme minuend − subtrahend = difference
(wikipedia) , je mets la date la plus récente en premier dans la liste des paramètres.
Notez que cela fonctionne très bien pour les dates antérieures à 1900, même si ces dates ont des représentations internes de l'année négatives, grâce aux règles de soustraction des nombres négatifs ...
> elapsed_months("1791-01-10", "1776-07-01")
[1] 174
Il peut y avoir un moyen plus simple. Ce n'est pas une fonction mais ce n'est qu'une ligne.
length(seq(from=date1, to=date2, by='month')) - 1
par exemple.
> length(seq(from=Sys.Date(), to=as.Date("2020-12-31"), by='month')) - 1
Produit:
[1] 69
Ceci calcule le nombre de mois entiers entre les deux dates. Supprimez -1 si vous souhaitez inclure le mois/reste en cours qui n'est pas un mois entier.
Je pense que ceci est une réponse plus précise à la question posée en termes de parité avec la fonction MathWorks
Fonction mois MathWorks
MyMonths = months(StartDate, EndDate, EndMonthFlag)
Mon code R
library(lubridate)
interval(mdy(10012015), today()) %/% months(1)
Sortie (comme lorsque le code a été exécuté en avril 2016)
[1] 6
Lubridate [package] fournit des outils facilitant l'analyse et la manipulation des dates. Ces outils sont regroupés ci-dessous par objectif commun. Vous trouverez plus d'informations sur chaque fonction dans la documentation d'aide.
intervalle {lubridate} crée un objet de classe Interval avec les dates de début et de fin spécifiées. Si la date de début est antérieure à la date de fin, l'intervalle sera positif. Sinon, ce sera négatif
aujourd'hui {lubridate} La date du jour
mois {Base} Extrait le mois Il s'agit de fonctions génériques: les méthodes des classes de date-heure internes sont documentées ici.
% /% {base} indique une division entière AKA (x% /% y) (jusqu'à erreur d'arrondi)
Il y a un message semblable au vôtre dans la liste de diffusion de R-Help (j'avais précédemment mentionné une liste CRAN).
Ici le lien . Il y a deux solutions suggérées:
#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
comme ceci:as.Date.numeric <- function(x) structure(floor(x+.001), class = "Date") sapply(d2, function(d2) length(seq(d1, as.Date(d2), by = "month")))-1
library(lubridate)
case1: fonction naïve
mos<-function (begin, end) {
mos1<-as.period(interval(ymd(begin),ymd(end)))
mos<-mos1@year*12+mos1@month
mos
}
case2: si vous avez besoin de ne considérer que 'Mois' indépendamment de 'Jour'
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<-mob1@year*12+mob1@month
mob
}
Exemple :
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
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)
Différence en mois = 12 * différence en années + différence en mois.
Il peut être nécessaire de corriger la suite en utilisant la condition
ifelse
. pour les soustractions du mois
Pour moi c'est ce qui a fonctionné:
library(lubridate)
Pagos$Datediff <- (interval((Pagos$Inicio_FechaAlta), (Pagos$Inicio_CobFecha)) %/% months(1))
La sortie est le nombre de mois entre deux dates et stocké dans une colonne du cadre de données Pagos.
Voici un autre moyen rapide et pratique:
day1 <- as.Date('1991/04/12')
day2 <- as.Date('2019/06/10')
round(as.numeric(day2 - day1)/30.42)
[1] 338
Date différence en mois
$date1 = '2017-01-20';
$date2 = '2019-01-20';
$ts1 = strtotime($date1);
$ts2 = strtotime($date2);
$year1 = date('Y', $ts1);
$year2 = date('Y', $ts2);
$month1 = date('m', $ts1);
$month2 = date('m', $ts2);
echo $joining_months = (($year2 - $year1) * 12) + ($month2 - $month1);