Conversion de l'année et du mois (format «aaaa-mm») en une date?

91

J'ai un ensemble de données qui ressemble à ceci:

Month    count
2009-01  12
2009-02  310
2009-03  2379
2009-04  234
2009-05  14
2009-08  1
2009-09  34
2009-10  2386

Je veux tracer les données (mois comme valeurs x et compte comme valeurs y). Puisqu'il y a des lacunes dans les données, je souhaite convertir les informations du mois en une date. J'ai essayé:

as.Date("2009-03", "%Y-%m")

Mais cela n'a pas fonctionné. Qu'est-ce qui ne va pas? Il semble que as.Date () nécessite également un jour et n'est pas en mesure de définir une valeur standard pour la journée? Quelle fonction résout mon problème?

R_User
la source

Réponses:

57

Essaye ça. (Ici, nous utilisons text=Linespour garder l'exemple autonome, mais en réalité, nous le remplacerions par le nom du fichier.)

Lines <- "2009-01  12
2009-02  310
2009-03  2379
2009-04  234
2009-05  14
2009-08  1
2009-09  34
2009-10  2386"

library(zoo)
z <- read.zoo(text = Lines, FUN = as.yearmon)
plot(z)

L'axe X n'est pas si joli avec ces données, mais si vous avez plus de données en réalité, cela pourrait être correct ou vous pouvez utiliser le code pour un axe X sophistiqué montré dans la section des exemples de ?plot.zoo.

La série zoo z, qui est créée ci-dessus a un "yearmon"index temporel et ressemble à ceci:

> z
Jan 2009 Feb 2009 Mar 2009 Apr 2009 May 2009 Aug 2009 Sep 2009 Oct 2009 
      12      310     2379      234       14        1       34     2386 

"yearmon" peut également être utilisé seul:

> as.yearmon("2000-03")
[1] "Mar 2000"

Remarque:

  1. "yearmon" les objets de classe sont triés dans l'ordre du calendrier.

  2. Cela tracera les points mensuels à des intervalles également espacés, ce qui est probablement ce qui est souhaité; Cependant, si l'on voulait tracer les points espacés à intervalles espacés dans inégalement proportionnellement au nombre de jours dans chaque mois , puis convertir l'indice de zla "Date"classe: time(z) <- as.Date(time(z)).

G. Grothendieck
la source
76

Puisque les dates correspondent à une valeur numérique et à une date de début, vous avez en effet besoin du jour. Si vous avez vraiment besoin que vos données soient au format Date, vous pouvez simplement fixer le jour au premier de chaque mois manuellement en le collant à la date:

month <- "2009-03"
as.Date(paste(month,"-01",sep=""))
Sacha Epskamp
la source
Quels autres formats de dates existe-t-il? J'ai vu quelque chose avec POSIX et quelque chose avec ISO, mais je ne sais pas si ce sont des formats différents. Je pensais que ce ne sont que des fonctions, ...
R_User
19
Il convient de noter que vous pouvez spécifier le jour comme étant le même dans le formateur, afin que vous puissiez faire as.Date(month, format='%Y-%m-01')et obtenir le même résultat. Cela me semble préférable car spécifier la même date chaque mois concerne davantage le format de la date que la manipulation de la chaîne, mais peut-être que c'est absurde.
JBecker
21
@JBecker votre suggestion ne fonctionne pas pour moi. > as.Date("2016-01", format="%Y-%m-01") # [1] NA. J'utilise R 3.3.1
n8sty
26

La solution la plus concise si vous avez besoin que les dates soient au format Date:

library(zoo)
month <- "2000-03"
as.Date(as.yearmon(month))
[1] "2000-03-01"

as.Date fixera le premier jour de chaque mois à un objet yearmon pour vous.

Ben Rollert
la source
23

Vous pouvez également y parvenir avec les fonctions parse_date_timeou fast_strptimedu lubridate-package:

> parse_date_time(dates1, "ym")
[1] "2009-01-01 UTC" "2009-02-01 UTC" "2009-03-01 UTC"

> fast_strptime(dates1, "%Y-%m")
[1] "2009-01-01 UTC" "2009-02-01 UTC" "2009-03-01 UTC"

La différence entre ces deux éléments est que cela parse_date_timepermet une spécification de format de style lubridate, tout en fast_strptimeexigeant la même spécification de format que strptime.

Pour spécifier le fuseau horaire, vous pouvez utiliser le tz-paramètre:

> parse_date_time(dates1, "ym", tz = "CET")
[1] "2009-01-01 CET" "2009-02-01 CET" "2009-03-01 CET"

Lorsque vous avez des irrégularités dans vos données date-heure, vous pouvez utiliser le truncatedparamètre -pour spécifier le nombre d'irrégularités autorisées:

> parse_date_time(dates2, "ymdHMS", truncated = 3)
[1] "2012-06-01 12:23:00 UTC" "2012-06-01 12:00:00 UTC" "2012-06-01 00:00:00 UTC"

Données utilisées:

dates1 <- c("2009-01","2009-02","2009-03")
dates2 <- c("2012-06-01 12:23","2012-06-01 12",'2012-06-01")
Jaap
la source
ayant converti une variable de caractère à formater à l' dateaide parse_date_time, est - il possible de le voir dans un ordre différent de celui en "2009-01-01 UTC"utilisant lubridatepackage? Je préférerais voir le jour en premier dans mon ensemble de données, par exemple 01-01-2009.
user63230
1
@ user63230 Voir ?format; par exemple: format(your_date, "%d-%m-%Y"). Il y a cependant un inconvénient à cela: vous récupérerez une valeur de personnage et non une date.
Jaap
Merci mais j'essayais d'éviter formatpour la raison que vous mentionnez, je pensais qu'il pourrait y avoir un moyen d'intégrer cela dans le lubridatepackage, mais il semble que ce ne soit pas le cas.
user63230
12

Utilisation du package à tout moment :

library(anytime)

anydate("2009-01")
# [1] "2009-01-01"
zx8754
la source
C'est un peu bizarre qu'il choisisse "01-01", y a-t-il quelque chose dans la documentation sur le choix? Peut-être plus illustratif pour montrer également anydate("2009-03")s'il choisit toujours le premier jour du mois.
lmo
@lmo n'a pas vérifié les documents, je dirais que c'est une pratique "courante" lorsque jj manque pour choisir le 1er jour.
zx8754
2
Ça a du sens. Je me suis vaguement souvenu de moi, puis j'ai trouvé ce qui avait déclenché le commentaire. Dans la section Note de ?strptime: la chaîne d'entrée n'a pas besoin de spécifier complètement la date: il est supposé que les secondes, minutes ou heures non spécifiées sont égales à zéro et qu'une année, un mois ou un jour non spécifié est celui en cours. (Cependant, si un mois est spécifié, le jour de ce mois doit être spécifié par% d ou% e car le jour en cours du mois n'a pas besoin d'être valide pour le mois spécifié.) Il semble que la réponse de mégatron contienne un élément similaire de la documentation de as.Date.
lmo
pendant des années avant 1900, cela ne fonctionne pas. Par exemple, j'ai essayé cecianytime('1870-01')
msh855
5

En effet, comme cela a été mentionné ci-dessus (et ailleurs sur SO), pour convertir la chaîne en une date, vous avez besoin d'une date précise du mois. Depuis la as.Date()page de manuel:

Si la chaîne de date ne spécifie pas complètement la date, la réponse renvoyée peut être spécifique au système. Le comportement le plus courant consiste à supposer qu'une année, un mois ou un jour manquant est celui en cours. Si elle spécifie une date de manière incorrecte, des implémentations fiables donneront une erreur et la date sera signalée comme NA. Malheureusement, certaines implémentations courantes (telles que glibc) ne sont pas fiables et devinent la signification voulue.

Une solution simple serait de coller la date "01"à chaque date et de l'utiliser strptime()pour l'indiquer comme premier jour de ce mois.


Pour ceux qui recherchent un peu plus d'informations sur les dates et heures de traitement en R:

Dans R, les heures utilisent POSIXctet les POSIXltclasses et les dates utilisent la Dateclasse.

Les dates sont enregistrées en nombre de jours depuis le 1er janvier 1970 et les heures en nombre de secondes depuis le 1er janvier 1970.

Ainsi, par exemple:

d <- as.Date("1971-01-01")
unclass(d)  # one year after 1970-01-01
# [1] 365

pct <- Sys.time()  # in POSIXct
unclass(pct)  # number of seconds since 1970-01-01
# [1] 1450276559
plt <- as.POSIXlt(pct)
up <- unclass(plt)  # up is now a list containing the components of time
names(up)
# [1] "sec"    "min"    "hour"   "mday"   "mon"    "year"   "wday"   "yday"   "isdst"  "zone"  
# [11] "gmtoff"
up$hour
# [1] 9

Pour effectuer des opérations aux dates et heures:

plt - as.POSIXlt(d)
# Time difference of 16420.61 days

Et pour traiter les dates, vous pouvez utiliser strptime()(en empruntant ces exemples à la page de manuel):

strptime("20/2/06 11:16:16.683", "%d/%m/%y %H:%M:%OS")
# [1] "2006-02-20 11:16:16 EST"

# And in vectorized form:
dates <- c("1jan1960", "2jan1960", "31mar1960", "30jul1960")
strptime(dates, "%d%b%Y")
# [1] "1960-01-01 EST" "1960-01-02 EST" "1960-03-31 EST" "1960-07-30 EDT"
Megatron
la source
1

Je pense que la solution de @ ben-rollert est une bonne solution.

Vous devez juste faire attention si vous souhaitez utiliser cette solution dans une fonction à l'intérieur d'un nouveau package.

Lors du développement de packages, il est recommandé d'utiliser la syntaxe packagename::function_name()(voir http://kbroman.org/pkg_primer/pages/depends.html ).

Dans ce cas, vous devez utiliser la version de as.Date()définie par la zoobibliothèque.

Voici un exemple :

> devtools::session_info()
Session info ----------------------------------------------------------------------------------------------------------------------------------------------------
 setting  value                       
 version  R version 3.3.1 (2016-06-21)
 system   x86_64, linux-gnu           
 ui       RStudio (1.0.35)            
 language (EN)                        
 collate  C                           
 tz       <NA>                        
 date     2016-11-09                  

Packages --------------------------------------------------------------------------------------------------------------------------------------------------------

 package  * version date       source        
 devtools   1.12.0  2016-06-24 CRAN (R 3.3.1)
 digest     0.6.10  2016-08-02 CRAN (R 3.2.3)
 memoise    1.0.0   2016-01-29 CRAN (R 3.2.3)
 withr      1.0.2   2016-06-20 CRAN (R 3.2.3)

> as.Date(zoo::as.yearmon("1989-10", "%Y-%m")) 
Error in as.Date.default(zoo::as.yearmon("1989-10", "%Y-%m")) : 
  do not know how to convert 'zoo::as.yearmon("1989-10", "%Y-%m")' to class “Date”

> zoo::as.Date(zoo::as.yearmon("1989-10", "%Y-%m"))
[1] "1989-10-01"

Donc, si vous développez un package, la bonne pratique est d'utiliser:

zoo::as.Date(zoo::as.yearmon("1989-10", "%Y-%m"))
PAC
la source