web-dev-qa-db-fra.com

Nombre de mois entre deux dates

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

55
knguyen

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.

51
Dirk Eddelbuettel

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
39
pbnelson

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.

31
Dominic

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)

27
mtelesha

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:

  • Il y a une moyenne de 365,25/12 jours par mois, donc l'expression suivante indique le nombre de mois entre d1 et d2:
#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))
  • Une autre possibilité consiste à obtenir la longueur de 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
11
Manoel Galdino
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
5
hyunwoo jeong
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

4
Ajay Ohri

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.

2
EDUARDO ROLDAN

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

0
JAQuent

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);
0
Kamlesh