web-dev-qa-db-fra.com

Comprendre les dates et tracer un histogramme avec ggplot2 dans R

Question principale

J'ai des problèmes pour comprendre pourquoi la gestion des dates, des étiquettes et des pauses ne fonctionne pas comme je m'y attendais dans R lorsque j'essayais de faire un histogramme avec ggplot2.

Je recherche:

  • Un histogramme de la fréquence de mes rendez-vous
  • Coche centrée sous les barres correspondantes
  • Étiquettes de date au format %Y-b
  • Limites appropriées; espace vide minimisé entre le bord de l'espace de la grille et les barres les plus à l'extérieur

J'ai téléchargé mes données sur Pastebin pour rendre cela reproductible. J'ai créé plusieurs colonnes car je n'étais pas sûr de la meilleure façon de procéder:

> dates <- read.csv("http://Pastebin.com/raw.php?i=sDzXKFxJ", sep=",", header=T)
> 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 . Cependant, je voulais un formatage %Y-%b, J'ai donc cherché et essayé les éléments suivants, en fonction de 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 de l'axe des x correct
  • La distribution de fréquence a changé de forme (problème de largeur de bande?)
  • Les graduations n'apparaissent pas centrées sous les barres
  • Les xlims ont également changé

J'ai travaillé sur l'exemple dans la documentation ggplot2 dans la section scale_x_date Et geom_line() semble casser, étiqueter et centrer correctement les ticks lorsque je l'utilise avec mon même données de 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 regardé 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)

Sur la base de 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))

Graphique basé sur l'approche d'edgester:

edgester-plot

Graphique basé sur l'approche de Gauden:

gauden-plot

Notez les points suivants:

  • lacunes dans l'intrigue 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
  • l'intrigue d'edgester commence à 2008-avril et se termine à 2012-mai. Ceci est correct sur la base d'une valeur minimale dans les données du 2008-04-01 et d'une date maximale du 2012-05-01. Pour une raison quelconque, l'intrigue de Gauden commence en 2008-mars et parvient toujours à se terminer en 2012-mai. Après avoir compté les bacs et lu le long des étiquettes du mois, pour la vie de moi, je ne peux pas savoir quel complot a un extra ou il manque un bac de l'histogramme!

Des réflexions sur les différences ici? méthode d'edgester pour créer un décompte séparé


Références connexes

En passant, voici d'autres emplacements qui contiennent des informations sur les dates et ggplot2 pour les passants à la recherche d'aide:

  • Commencé ici sur 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 est faux et a perdu mon temps.
  • n autre article learnr recrée une série chronologique dans ggplot2, mais n'était pas vraiment applicable à ma situation.
  • r-bloggers a un article à ce sujet , mais il semble obsolète. La simple option format= Ne fonctionnait pas pour moi.
  • Cette SO question joue avec les pauses et les étiquettes. J'ai essayé de traiter mon vecteur Date comme continu et je ne pense pas que cela fonctionne si bien. Il on aurait dit qu'il recouvrait le même texte d'étiquette encore et encore, donc les lettres semblaient un peu bizarres. La distribution est en quelque sorte correcte mais il y a des pauses bizarres. Ma tentative basée sur la réponse acceptée était comme ça ( résultat ici ).
58
Hendy

MISE À JOUR

Version 2: Utilisation de la classe Date

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

The Target Plot v2

date-based histogram

Le Code v2

Et voici (un peu excessivement) du 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, dessinant sans agrégation, et fixant les limites sur l'axe des x entre le début de 2009 et la fin de 2011.

The Target Plot v1

plot with limits set in 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 sûr, cela pourrait faire avec le jeu avec les options d'étiquette sur l'axe, mais c'est pour compléter le tracé avec une routine courte et propre dans le package de traçage.

32
gauden

Je pense que l'élément clé est que vous devez faire le calcul de fréquence en dehors de ggplot. Utilisez agrégat () avec geom_bar (stat = "identité") pour obtenir un histogramme sans les facteurs réorganisé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)
5
edgester

Le graphique d'erreur sous le titre "Graphique basé sur l'approche de Gauden" est dû au paramètre binwidth: ... + Geom_histogram (binwidth = 30, color = "white") + ... Si nous changeons la valeur de 30 en un valeur inférieure à 20, comme 10, vous obtiendrez toutes les fréquences.

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

0
Marco Guado