2011-06-05 1 views
61

J'ai un ensemble de données qui ressemble à ceci:Conversion de l'année et du mois (format "aaaa-mm") en une date?

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 de x et compte comme valeurs y). Comme il y a des lacunes dans les données, je veux convertir l'information pour le 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épondre

40

essayer. (Ici, nous utilisons text=Lines pour garder l'exemple autonome mais en réalité, nous le remplacer 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 jolie avec ces données, mais si vous avez plus de données en réalité il peut être ok ou vous pouvez utiliser le code pour un axe X fantaisie montré dans la section des exemples de ?plot.zoo.

La série zoo, z, qui est créé ci-dessus présente un indice 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 être utilisé seul ainsi:

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

Note:

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

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

50

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 de vos données soient en format de date, il vous suffit de fixer le jour au premier de chaque mois manuellement en collant à la date:

month <- "2009-03" 
as.Date(paste(month,"-01",sep="")) 
+0

Quels sont les autres formats de dates? 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, ... –

+14

À noter que vous pouvez spécifier le jour comme étant le même dans le formateur, de sorte que vous pouvez faire 'as.Date (mois, format = '% Y-% m-01') 'et atteindre le même résultat. Ce "me semble" préférable à moi puisque spécifier la même date dans chaque mois est plus sur le format de la date que sur la manipulation de la chaîne, mais peut-être que c'est un non-sens. – JBecker

+7

@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

21

La solution la plus concise si vous avez besoin des dates pour être au format Date:

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

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

2

En effet, comme cela a été mentionné ci-dessus (et ailleurs sur SO), afin de 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 commun consiste à supposer qu'une année, un mois ou un jour manquant est l'année en cours.Si elle spécifie une date de manière incorrecte, les implémentations fiables donneront une erreur et la date est 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 utiliser strptime() pour indiquer le premier jour de ce mois.


Pour ceux qui recherchent un peu plus d'information sur les dates de traitement et de temps dans R:

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

Les dates sont stockées en tant que le nombre de jours depuis le 1er Janvier 1970 et le temps sont stockés comme le 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 opérations sur les dates et heures:

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

et traiter les dates, vous pouvez utiliser strptime() (emprunter ces exemples de 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" 
-1

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

Vous devez juste faire attention si vous voulez utiliser cette solution dans une fonction d'un nouveau paquet. Lorsque vous développez des 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 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 êtes un paquet développer, la bonne pratique consiste à utiliser:

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

En utilisant anytime package:

library(anytime) 

anydate("2009-01") 
# [1] "2009-01-01" 
+0

C'est un peu bizarre de choisir "01-01", y a-t-il quelque chose dans la documentation sur le choix? Peut-être plus illustratif de montrer également 'anydate (" 2009-03 ")' si il choisit toujours le premier jour du mois. – lmo

+0

@lmo n'a pas vérifié les docs, je dirais que c'est une pratique "courante" quand dd manque pour choisir le 1er jour. – zx8754

+2

Cela a du sens. Je me souvenais vaguement et ensuite trouvé ce qui a 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 nulles et une année, un mois ou un jour non spécifié est le jour courant. (Cependant, si un mois est spécifié, le jour de ce mois doit être spécifié par% d ou% e, car le jour actuel du mois n'a pas besoin d'être valide pour le mois spécifié.) * Il semble que la réponse de mégatron contienne une pièce de documentation de 'as.Date'. – lmo

4

Vous pouvez également réaliser ceci avec la fonction parse_date_time ou fast_strptime ns de la 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 les deux est que parse_date_time permet pour la spécification de format de style lubridate, alors que fast_strptime nécessite la spécification même format que strptime.

Pour spécifier le fuseau horaire, vous pouvez utiliser le tz -parameter:

> 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 à jour en temps, vous pouvez utiliser le truncated -parameter pour spécifier le nombre d'irrégularités sont autorisés:

> 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 occasion:

dates1 <- c("2009-01","2009-02","2009-03") 
dates2 <- c("2012-06-01 12:23","2012-06-01 12",'2012-06-01") 
Questions connexes