Comprendre les dates et tracer un histogramme avec ggplot2 dans R

Question principale

J’ai du mal à comprendre pourquoi le traitement des dates, des étiquettes et des pauses ne fonctionne pas comme je l’aurais attendu dans R lorsque j’essaie de créer un histogramme avec ggplot2.

Je cherche:

  • Un histogramme de la fréquence de mes dates
  • Coche centrée sous les barres correspondantes
  • Étiquettes de date au format %Yb
  • Limites appropriées; espace vide minimisé entre le bord de la grid et les barres les plus à l’extérieur

J’ai téléchargé mes données sur pastebin pour les rendre reproductibles. J’ai créé plusieurs colonnes car je n’étais pas sûr de la meilleure façon de le faire:

 > dates  head(dates) YM Date Year Month 1 2008-Apr 2008-04-01 2008 4 2 2009-Apr 2009-04-01 2009 4 3 2009-Apr 2009-04-01 2009 4 4 2009-Apr 2009-04-01 2009 4 5 2009-Apr 2009-04-01 2009 4 6 2009-Apr 2009-04-01 2009 4 

Voici ce que j’ai essayé:

 library(ggplot2) library(scales) dates$converted <- as.Date(dates$Date, format="%Y-%m-%d") ggplot(dates, aes(x=converted)) + geom_histogram() + opts(axis.text.x = theme_text(angle=90)) 

Ce qui donne ce graphique . Je voulais cependant un formatage %Y-%b , alors j’ai cherché et essayé ce qui suit, basé sur ce SO :

 ggplot(dates, aes(x=converted)) + geom_histogram() + scale_x_date(labels=date_format("%Y-%b"), + breaks = "1 month") + opts(axis.text.x = theme_text(angle=90)) stat_bin: binwidth defaulted to range/30. Use 'binwidth = x' to adjust this. 

Cela me donne ce graphique

  • Format d’étiquette d’axe x correct
  • La dissortingbution de fréquence a changé de forme (problème de largeur de fichier?)
  • Les repères n’apparaissent pas centrés sous les barres
  • Les xlims ont également changé

J’ai parcouru l’exemple de la documentation ggplot2 à la section scale_x_date et geom_line() semble casser, étiqueter et centrer correctement les ticks lorsque je les utilise avec mes mêmes données sur l’axe des x. Je ne comprends pas pourquoi l’histogramme est différent.


Mises à jour basées sur les réponses d’edgester et de gauden

J’ai d’abord pensé que la réponse de gauden m’a aidé à résoudre mon problème, mais je suis maintenant perplexe après avoir examiné de plus près. Notez les différences entre les graphiques résultants des deux réponses après le code.

Supposons pour les deux:

 library(ggplot2) library(scales) dates <- read.csv("http://pastebin.com/raw.php?i=sDzXKFxJ", sep=",", header=T) 

Basé sur la réponse de @ edgester ci-dessous, j’ai pu faire ce qui suit:

 freqs <- aggregate(dates$Date, by=list(dates$Date), FUN=length) freqs$names <- as.Date(freqs$Group.1, format="%Y-%m-%d") ggplot(freqs, aes(x=names, y=x)) + geom_bar(stat="identity") + scale_x_date(breaks="1 month", labels=date_format("%Y-%b"), limits=c(as.Date("2008-04-30"),as.Date("2012-04-01"))) + ylab("Frequency") + xlab("Year and Month") + theme_bw() + opts(axis.text.x = theme_text(angle=90)) 

Voici ma tentative basée sur la réponse de gauden:

 dates$Date <- as.Date(dates$Date) ggplot(dates, aes(x=Date)) + geom_histogram(binwidth=30, colour="white") + scale_x_date(labels = date_format("%Y-%b"), breaks = seq(min(dates$Date)-5, max(dates$Date)+5, 30), limits = c(as.Date("2008-05-01"), as.Date("2012-04-01"))) + ylab("Frequency") + xlab("Year and Month") + theme_bw() + opts(axis.text.x = theme_text(angle=90)) 

Tracé basé sur l’approche d’Edgester:

edgester-plot

Terrain basé sur l’approche de gauden:

gauden-complot

Notez les points suivants:

  • les lacunes dans la plot de gauden pour 2009-déc et 2010-mars; table(dates$Date) révèle qu’il y a 19 instances de 2009-12-01 et 26 instances de 2010-03-01 dans les données
  • La plot d’edgester commence à 2008-avril et se termine à 2012-mai. Ceci est correct basé sur une valeur minimale dans les données du 2008-04-01 et une date maximale du 2012-05-01. Pour une raison quelconque, l’insortinggue de Gauden commence en 2008-mars et parvient encore à se terminer en 2012-mai. Après avoir compté les bacs et lu les étiquettes des mois, je n’arrive pas à déterminer, pour la durée de ma vie, quelle plot a un supplément ou s’il manque une case de l’histogramme!

Des reflections sur les différences ici? méthode de edgester pour créer un compte séparé


Références connexes

En passant, voici d’autres lieux qui contiennent des informations sur les dates et ggplot2 pour les passants en quête d’aide:

  • Commencé ici à learnr.wordpress, un blog R populaire. Il a déclaré que je devais mettre mes données au format POSIXct, ce que je pense maintenant être faux et perdre mon temps.
  • Un autre message d’apprentissage recrée une série chronologique dans ggplot2, mais n’était pas vraiment applicable à ma situation.
  • Les blogueurs ont un message à ce sujet , mais il semble obsolète. Le format= simple format= option ne fonctionnait pas pour moi.
  • Cette question SO joue avec les pauses et les étiquettes. J’ai essayé de traiter mon vecteur de Date de façon continue et je ne pense pas que cela fonctionne si bien. Il semblait que le texte de la même étiquette se superposait encore et encore, si bien que les lettres semblaient étranges. La dissortingbution est en quelque sorte correcte mais il y a des pauses impaires. Ma tentative basée sur la réponse acceptée était comme ça ( résultat ici ).

METTRE À JOUR

Version 2: Utilisation de la classe Date

Je mets à jour l’exemple pour montrer l’alignement des étiquettes et la définition des limites sur le tracé. Je démontre également que as.Date fonctionne bien lorsqu’il est utilisé de manière cohérente (en fait, il convient probablement mieux à vos données que mon exemple précédent).

Le tracé cible v2

histogramme basé sur la date

Le code v2

Et voici (un peu excessivement) le code commenté:

 library("ggplot2") library("scales") dates <- read.csv("http://pastebin.com/raw.php?i=sDzXKFxJ", sep=",", header=T) dates$Date <- as.Date(dates$Date) # convert the Date to its numeric equivalent # Note that Dates are stored as number of days internally, # hence it is easy to convert back and forth mentally dates$num <- as.numeric(dates$Date) bin <- 60 # used for aggregating the data and aligning the labels p <- ggplot(dates, aes(num, ..count..)) p <- p + geom_histogram(binwidth = bin, colour="white") # The numeric data is treated as a date, # breaks are set to an interval equal to the binwidth, # and a set of labels is generated and adjusted in order to align with bars p <- p + scale_x_date(breaks = seq(min(dates$num)-20, # change -20 term to taste max(dates$num), bin), labels = date_format("%Y-%b"), limits = c(as.Date("2009-01-01"), as.Date("2011-12-01"))) # from here, format at ease p <- p + theme_bw() + xlab(NULL) + opts(axis.text.x = theme_text(angle=45, hjust = 1, vjust = 1)) p 

Version 1: Utilisation de POSIXct

J'essaie une solution qui fait tout dans ggplot2 , dessine sans agrégation et fixe les limites sur l'axe des x entre le début de 2009 et la fin de 2011.

Le tracé cible v1

tracer avec des limites définies dans ggplot2

Le code v1

 library("ggplot2") library("scales") dates <- read.csv("http://pastebin.com/raw.php?i=sDzXKFxJ", sep=",", header=T) dates$Date <- as.POSIXct(dates$Date) p <- ggplot(dates, aes(Date, ..count..)) + geom_histogram() + theme_bw() + xlab(NULL) + scale_x_datetime(breaks = date_breaks("3 months"), labels = date_format("%Y-%b"), limits = c(as.POSIXct("2009-01-01"), as.POSIXct("2011-12-01")) ) p 

Bien entendu, il pourrait être utile de jouer avec les options d’étiquette sur l’axe, mais cela permet de terminer le tracé avec une routine propre et courte dans l’ensemble de traçage.

Je pense que l’essentiel est de faire le calcul de fréquence en dehors de ggplot. Utilisez aggregate () avec geom_bar (stat = “identity”) pour obtenir un histogramme sans les facteurs réordonnés. Voici un exemple de code:

 require(ggplot2) # scales goes with ggplot and adds the needed scale* functions require(scales) # need the month() function for the extra plot require(lubridate) # original data #df<-read.csv("http://pastebin.com/download.php?i=sDzXKFxJ", header=TRUE) # simulated data years=sample(seq(2008,2012),681,replace=TRUE,prob=c(0.0176211453744493,0.302496328928047,0.323054331864905,0.237885462555066,0.118942731277533)) months=sample(seq(1,12),681,replace=TRUE) my.dates=as.Date(paste(years,months,01,sep="-")) df=data.frame(YM=strftime(my.dates, format="%Y-%b"),Date=my.dates,Year=years,Month=months) # end simulated data creation # sort the list just to make it pretty. It makes no difference in the final results df=df[do.call(order, df[c("Date")]), ] # add a dummy column for clarity in processing df$Count=1 # compute the frequencies ourselves freqs=aggregate(Count ~ Year + Month, data=df, FUN=length) # rebuild the Date column so that ggplot works freqs$Date=as.Date(paste(freqs$Year,freqs$Month,"01",sep="-")) # I set the breaks for 2 months to reduce clutter g<-ggplot(data=freqs,aes(x=Date,y=Count))+ geom_bar(stat="identity") + scale_x_date(labels=date_format("%Y-%b"),breaks="2 months") + theme_bw() + opts(axis.text.x = theme_text(angle=90)) print(g) # don't overwrite the previous graph dev.new() # just for grins, here is a faceted view by year # Add the Month.name factor to have things work. month() keeps the factor levels in order freqs$Month.name=month(freqs$Date,label=TRUE, abbr=TRUE) g2<-ggplot(data=freqs,aes(x=Month.name,y=Count))+ geom_bar(stat="identity") + facet_grid(Year~.) + theme_bw() print(g2) 

Le graphique d’erreur sous le titre “Tracé basé sur l’approche de Gauden” est dû au paramètre binwidth: … + Geom_histogram (binwidth = 30, color = “white”) + … Si l’on change la valeur de 30 en valeur inférieure à 20, telle que 10, vous obtiendrez toutes les fréquences.

En statistique les valeurs sont plus importantes que la présentation est plus importante un graphisme fade à une image très jolie mais avec des erreurs.