2017-05-18 1 views
1

Plus qu'une solution Je voudrais comprendre la raison pour laquelle quelque chose qui devrait être assez facile, c'est en fait pas.ggplot2: yearmon scale et geom_bar

[J'emprunte une partie du code d'un autre poste qui a abordé la question, mais il a fini avec une solution ne me plaisait pas]

library(ggplot2) 
library(xts) 
library(dplyr) 
library(scales) 

csvData <- "dt,status 
2015-12-03,1 
2015-12-05,1 
2015-12-05,0 
2015-11-24,1 
2015-10-17,0 
2015-12-18,0 
2016-06-30,0 
2016-05-21,1 
2016-03-31,0 
2015-12-31,0" 

tmp <- read.csv(textConnection(csvData)) 
tmp$dt <- as.Date(tmp$dt) 
tmp$yearmon <- as.yearmon(tmp$dt) 
tmp$status <- as.factor(tmp$status) 

### Not good. Why? 
ggplot(tmp, aes(x = yearmon, fill = status)) + 
    geom_bar() + 
    scale_x_yearmon() 

### Almost good but long-winded and ticks not great 
chartData <- tmp %>% 
    group_by(yearmon, status) %>% 
    summarise(count = n()) %>% 
    as.data.frame() 
ggplot(chartData, aes(x = yearmon, y = count, fill = status)) + 
    geom_col() + 
    scale_x_yearmon() 

La première parcelle est tout faux; la seconde est presque parfaite (les ticks sur l'axe X ne sont pas super mais je peux vivre avec ça). Est-ce que geom_bar() n'est pas censé effectuer le travail de comptage que je dois effectuer manuellement dans le second tableau?

PREMIER TABLEAU poor plot

TABLEAU DEUXIÈME better plot

Ma question est: pourquoi est le premier graphique si pauvre? Il y a un avertissement qui est censé suggérer quelque chose ("position_stack nécessite des intervalles x non chevauchants") mais je ne comprends vraiment pas. Merci.

MA REPONSE PERSONNEL

Ce que j'ai appris (merci beaucoup à vous tous!):

  • Même s'il y a un scale_#_yearmon ou scale_#_date, malheureusement ggplot traite ces types d'objets en tant que nombres continus. Cela rend geom_bar inutilisable.
  • geom_histogram pourrait faire l'affaire. Mais vous perdez le contrôle sur les parties pertinentes de l'esthétique.
  • ligne de fond: vous devez groupe/somme avant de dresser une carte
  • Je ne sais pas (si vous prévoyez d'utiliser ggplot2) XTS ou lubridate sont vraiment utiles pour ce que je voulais atteindre. Je soupçonne pour tout cas continu - date-sage - ils seront parfaits.

Tous, j'ai fini avec ce qui ne parfaitement ce que je suis après (remarquez comment il n'y a pas besoin de XTS ou lubridate):

library(ggplot2) 
library(dplyr) 
library(scales) 

csvData <- "dt,status 
2015-12-03,1 
2015-12-05,1 
2015-12-05,0 
2015-11-24,1 
2015-10-17,0 
2015-12-18,0 
2016-06-30,0 
2016-05-21,1 
2016-03-31,0 
2015-12-31,0" 

tmp <- read.csv(textConnection(csvData)) 
tmp$dt <- as.Date(tmp$dt) 
tmp$yearmon <- as.Date(format(tmp$dt, "%Y-%m-01")) 
tmp$status <- as.factor(tmp$status) 

### GOOD 
chartData <- tmp %>% 
    group_by(yearmon, status) %>% 
    summarise(count = n()) %>% 
    as.data.frame() 

ggplot(chartData, aes(x = yearmon, y = count, fill = status)) + 
    geom_col() + 
    scale_x_date(labels = date_format("%h-%y"), 
       breaks = seq(from = min(chartData$yearmon), 
          to = max(chartData$yearmon), by = "month")) 

SORTIE FINALE final plot

+0

Je ne vois aucune différence entre le premier et le deuxième graphique. Pouvez-vous poster les images de vos complots et souligner ce qui ne va pas dans le premier complot? –

+0

Fait à la demande. Cela pourrait-il être une sorte de problème sur la version plate-forme/paquet? Je suis sur WIN10; R version 3.4.0 (2017-04-21); ggplot2 2.2.1 –

+0

Je voudrais utiliser à la place: ggplot (tmp, aes (x = date_table (dt, "mois"), remplir = statut)) + geom_bar() + scale_x_date (labels = date_format ("% Y-% b ")), ce qui donne un meilleur axe x. –

Répondre

1

La raison pour laquelle la première parcelle est vissée est fondamentalement ggplot2 ne correspond pas exactement à la yearmon est. Comme vous le voyez ici, c'est juste un num en interne avec des étiquettes.

> as.numeric(tmp$yearmon) 
[1] 2015.917 2015.917 2015.917 2015.833 2015.750 2015.917 2016.417 2016.333 2016.167 2015.917 

Ainsi, lorsque vous tracez sans l'agrégation précédente, la barre est étalée.Vous devez attribuer binwidth approprié à l'aide geom_histogram() comme ceci:

ggplot(tmp, aes(x = yearmon, fill = status)) + 
    geom_histogram(binwidth = 1/12) + 
    scale_x_yearmon() 

1/12 correspond à 12 mois par année.

Pour une parcelle après agrégation, comme le suggère @ed_sans, je préfère aussi lubridate car je connais mieux comment changer les graduations et modifier les étiquettes des axes.

chartData <- tmp %>% 
    mutate(ym = floor_date(dt,"month")) %>% 
    group_by(ym, status) %>% 
    summarise(count = n()) %>% 
    as.data.frame() 

ggplot(chartData, aes(x = ym, y = count, fill = status)) + 
    geom_col() + 
    scale_x_date(labels = date_format("%Y-%m"), 
       breaks = as.Date("2015-09-01") + 
       months(seq(0, 10, by = 2)))