web-dev-qa-db-fra.com

Conversion de l’année et du mois (format "aaaa-mm") en date?

J'ai un jeu 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 en tant que valeurs x et compte en tant que valeurs y). Comme il existe 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 le jour? Quelle fonction résout mon problème?

72
R_User

Essaye ça. (Ici, nous utilisons text=Lines pour 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 aussi beau avec ces données, mais si vous avez plus de données dans la réalité, cela peut être correct ou vous pouvez utiliser le code pour un axe X fantaisie présenté dans la section exemples de ?plot.Zoo.

La série Zoo, z, créée ci-dessus a un index de temps "yearmon" 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. Les objets de la classe "yearmon" sont triés dans l'ordre du calendrier.

  2. Cela permettra de tracer les points mensuels à intervalles égaux, ce qui correspond probablement à ce que vous souhaitez; Toutefois, si vous souhaitez tracer les points à des intervalles inégaux, en fonction du nombre de jours de chaque mois, convertissez l'index de z en "Date" classe: time(z) <- as.Date(time(z)).

50
G. Grothendieck

Comme les dates correspondent à une valeur numérique et à une date de début, vous avez effectivement besoin de la journée. 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=""))
59
Sacha Epskamp

La solution la plus concise si vous souhaitez 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. 

23
Ben Rollert

Vous pouvez également y parvenir avec les fonctions parse_date_time ou fast_strptime du package lubridate-:

> 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 les deux réside dans le fait que parse_date_time permet la spécification de format de type lubrifiant, alors que fast_strptime requiert la même spécification de format que strptime.

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

> 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 de date-heure, vous pouvez utiliser le paramètre truncated- 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")
12
Jaap

Utiliser à tout moment package:

library(anytime)

anydate("2009-01")
# [1] "2009-01-01"
10
zx8754

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

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. S'il spécifie une date de manière incorrecte, des implémentations fiables donneront une erreur et la date sera indiquée comme étant NA. Malheureusement, certaines implémentations courantes (telles que glibc) ne sont pas fiables et supposent la signification voulue.

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


Pour ceux qui recherchent un peu plus d'informations sur le traitement des dates et des heures dans R:

En R, times utilise POSIXct et POSIXlt classes et les dates utilisent la classe Date.

Les dates sont stockées sous forme de nombre de jours depuis le 1er janvier 1970 et les heures sous forme de nombre de secondes depuis le 1er janvier 1970.

Donc, 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 sur les 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"
4
Megatron

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 paquets, 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 bibliothèque Zoo

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 paquet, la bonne pratique consiste à utiliser: 

Zoo::as.Date(Zoo::as.yearmon("1989-10", "%Y-%m"))
0
PAC