95 votes

Obtenez la différence entre les dates en termes de semaines, de mois, de trimestres et d'années.

J'ai deux dates, disons 14.01.2013 et 26.03.2014.

J'aimerais obtenir la différence entre ces deux dates en termes de semaines (?), mois (dans l'exemple 14), trimestres (4) et années (1).

Savez-vous quelle est la meilleure façon d'obtenir cela ?

1 votes

Pour les semaines, j'ai trouvé la différence suivante : difftime(time1, time2, units="weeks"). Malheureusement, cela ne fonctionne pas pour les mois, les trimestres, les années.

86voto

ddg Points 2383

Que diriez-vous de ceci:

# obtenir la différence entre les dates "01.12.2013" et "31.12.2013"

# semaines
difftime(strptime("26.03.2014", format = "%d.%m.%Y"),
strptime("14.01.2013", format = "%d.%m.%Y"),units="weeks")
Temps de différence de 62.28571 semaines

# mois
(as.yearmon(strptime("26.03.2014", format = "%d.%m.%Y"))-
as.yearmon(strptime("14.01.2013", format = "%d.%m.%Y")))*12
[1] 14

# trimestres
(as.yearqtr(strptime("26.03.2014", format = "%d.%m.%Y"))-
as.yearqtr(strptime("14.01.2013", format = "%d.%m.%Y")))*4
[1] 4

# années
year(strptime("26.03.2014", format = "%d.%m.%Y"))-
year(strptime("14.01.2013", format = "%d.%m.%Y"))
[1] 1

as.yearmon() et as.yearqtr() sont dans le package zoo. year() est dans le package lubridate. Que pensez-vous?

16 votes

Cette réponse nécessite de la prudence... elle considérera le 31 décembre 2013 comme étant 1 an différent du lendemain, le 1er janvier 2014. Parfois cela est souhaité, mais souvent non.

1 votes

En étendant la mise en garde de Gregor : année donnera la différence en années calendaires uniquement, donc si vous avez besoin de connaître la différence en une fraction d'année, ce ne sera pas approprié.

0 votes

'format' + les valeurs par défaut peuvent rendre cela plus facile à taper : difftime(format("2014-03-26"), format("2013-01-14"), unités = "semaines") Différence de temps de 62.28571 semaines

61voto

rysqui Points 93

Toutes les réponses existantes sont imparfaites (IMO) et font soit des hypothèses sur la sortie souhaitée, soit ne fournissent pas de flexibilité pour la sortie souhaitée.

Sur la base des exemples de l'OP et des réponses attendues de l'OP, je pense que ce sont les réponses que vous recherchez (plus quelques exemples supplémentaires qui facilitent l'extrapolation).

(Cela ne nécessite que R de base et ne nécessite pas zoo ou lubridate)

Convertir en objets Datetime

date_strings = c("14.01.2013", "26.03.2014")
datetimes = strptime(date_strings, format = "%d.%m.%Y") # convertir en objets datetime

Différence en jours

Vous pouvez utiliser la différence en jours pour obtenir certaines de nos réponses ultérieures.

diff_in_days = difftime(datetimes[2], datetimes[1], units = "days") # jours
diff_in_days
#Différence de temps de 435.9583 jours

Différence en semaines

La différence en semaines est un cas spécial de units = "weeks" dans difftime()

diff_in_weeks = difftime(datetimes[2], datetimes[1], units = "weeks") # semaines
diff_in_weeks
#Différence de temps de 62.27976 semaines

Notez que c'est la même chose que de diviser notre diff_in_days par 7 (7 jours dans une semaine)

as.double(diff_in_days)/7
#[1] 62.27976

Différence en années

Avec une logique similaire, nous pouvons déduire les années à partir de diff_in_days

diff_in_years = as.double(diff_in_days)/365 # années absolues
diff_in_years
#[1] 1.194406

Il semble que vous attendiez une différence en années de "1", donc je suppose que vous voulez simplement compter des années calendaires absolues ou quelque chose, ce que vous pouvez facilement faire en utilisant floor()

# obtenir la sortie souhaitée, selon votre définition des 'années'
floor(diff_in_years)
#[1] 1

Différence en trimestres

# obtenir la sortie souhaitée pour les trimestres, selon votre définition des 'trimestres'
floor(diff_in_years * 4)
#[1] 4

Différence en mois

Vous pouvez calculer cela comme une conversion à partir de diff_years

# mois, définis comme des mois calendaires absolus (ce que vous voulez peut-être, étant donné les détails de votre question)
months_diff = diff_in_years*12
floor(month_diff)
#[1] 14

Je sais que cette question est ancienne, mais étant donné que je devais résoudre ce problème juste maintenant, j'ai pensé ajouter mes réponses. J'espère que cela vous aidera.

0 votes

Je pense que cela ne fonctionne pas, lorsque le months_diff est < 0.

0 votes

@timat pouvez-vous donner un exemple précis de deux chaînes de dates pour lesquelles cela ne fonctionne pas pour vous ?

1 votes

date_strings = c("14.07.2014", "10.03.2015") donne -4 au lieu de 7 mois selon la première définition.

15voto

plannapus Points 9026

Pendant des semaines, vous pouvez utiliser la fonction difftime:

date1 <- strptime("14.01.2013", format="%d.%m.%Y")
date2 <- strptime("26.03.2014", format="%d.%m.%Y")
difftime(date2,date1,units="weeks")
Différence de temps de 62.28571 semaines

Mais difftime ne fonctionne pas avec des durées dépassant les semaines.
Ce qui suit est une solution très sous-optimale utilisant cut.POSIXt pour ces durées mais vous pouvez contourner le problème:

seq1 <- seq(date1,date2, by="days")
nlevels(cut(seq1,"months"))
15
nlevels(cut(seq1,"quarters"))
5
nlevels(cut(seq1,"years"))
2

Cependant, il s'agit du nombre de mois, de trimestres ou d'années englobés par votre intervalle de temps et non de la durée de votre intervalle de temps exprimée en mois, trimestres, années (puisque ces durées n'ont pas une durée constante). En tenant compte du commentaire que vous avez fait sur la réponse de @SvenHohenstein, je pense que vous pouvez utiliser nlevels(cut(seq1, "months")) - 1 pour ce que vous essayez d'accomplir.

14voto

Gregor Points 6270

J'ai écrit ceci pour une autre question, puis je suis tombé(e) ici.

library(lubridate)

#' Calculer l'âge
#' 
#' Par défaut, calcule l'âge typique en années, avec un arrondi appliqué de sorte que vous avez, par exemple, 5 ans du
#' 5e anniversaire jusqu'au jour avant votre 6e anniversaire. Définissez
#' \code{floor = FALSE} pour obtenir des âges décimaux, et changez \code{units}
#' pour des unités autres que les années.
#' @param dob date de naissance, le jour à partir duquel l'âge est calculé.
#' @param age.day la date à laquelle l'âge doit être calculé.
#' @param units unité de mesure de l'âge. Par défaut à \code{"years"}. Passé à \link{\code{duration}}.
#' @param floor boolean pour arrondir ou non le résultat. Par défaut à \code{TRUE}.
#' @return Âge en \code{units}. Sera un entier si \code{floor = TRUE}.
#' @examples
#' my.dob <- as.Date('1983-10-20')
#' age(my.dob)
#' age(my.dob, units = "minutes")
#' age(my.dob, floor = FALSE)
age <- function(dob, age.day = today(), units = "years", floor = TRUE) {
    calc.age = interval(dob, age.day) / duration(num = 1, units=units)
    if (floor) return(as.integer(floor(calc.age)))
    return(calc.age)
}

Exemples d'utilisation:

my.dob <- as.Date('1983-10-20')

age(my.dob)
# [1] 31

age(my.dob, floor = FALSE)
# [1] 31.15616

age(my.dob, units = "minutes")
# [1] 16375680

age(seq(my.dob, length.out = 6, by = "years"))
# [1] 31 30 29 28 27 26

0 votes

'new_interval' est obsolète; utilisez 'intervalle' à la place. Obsolète en version '1.5.0'.

0 votes

J'ai juste écrit cela pour une autre question, puis je suis tombé ici. Moi aussi! Petit conseil : utilisez des accolades après une instruction if : if (floor) { ... } et n'utilisez return que lorsque vous retournez quelque chose au milieu de votre fonction. La dernière ligne devrait simplement être calc.age.

1 votes

@MSBerends Ce ne sont que des directives de style. Je préfère beaucoup retourner explicitement avec mes fonctions - je trouve cela plus clair. Bien sûr, dans votre propre code, utilisez le style qui vous convient le mieux.

11voto

Tjebo Points 2775

Voici la réponse encore manquante de lubridate (bien que la fonction de Gregor soit basée sur ce package)

La documentation sur les timespan de lubridate est très utile pour comprendre la différence entre les périodes et les durées. J'aime aussi la cheatsheet de lubridate et ce fil très utile

library(lubridate)

dates <- c(dmy('14.01.2013'), dmy('26.03.2014'))

span <- dates[1] %--% dates[2] #création d'un objet intervalle

#création d'objets période
as.period(span, unit = 'year') 
#> [1] "1y 2m 12d 0H 0M 0S"
as.period(span, unit = 'month')
#> [1] "14m 12d 0H 0M 0S"
as.period(span, unit = 'day')
#> [1] "436d 0H 0M 0S"

Les périodes n'acceptent pas les semaines comme unités. Mais vous pouvez convertir des durées en semaines :

as.duration(span)/ dweeks(1)
#crée un objet durée (en secondes) et divise par la durée d'une semaine (en secondes)
#> [1] 62.28571

Créé le 2019-11-04 par le package reprex (v0.3.0)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X