Affichage des valeurs de données sur un graphique à barres empilées dans ggplot2

112

Je voudrais afficher les valeurs de données sur un graphique à barres empilées dans ggplot2. Voici ma tentative de code

Year      <- c(rep(c("2006-07", "2007-08", "2008-09", "2009-10"), each = 4))
Category  <- c(rep(c("A", "B", "C", "D"), times = 4))
Frequency <- c(168, 259, 226, 340, 216, 431, 319, 368, 423, 645, 234, 685, 166, 467, 274, 251)
Data      <- data.frame(Year, Category, Frequency)
library(ggplot2)
p <- qplot(Year, Frequency, data = Data, geom = "bar", fill = Category,     theme_set(theme_bw()))
p + geom_text(aes(label = Frequency), size = 3, hjust = 0.5, vjust = 3, position =     "stack") 

entrez la description de l'image ici

J'aimerais afficher ces valeurs de données au milieu de chaque partie. Toute aide à cet égard sera très appréciée. Merci

MYaseen208
la source
Question connexe: stackoverflow.com/questions/18994631/…
Tyler Rinker
Ce n'est pas vraiment le lieu d'un débat, mais je me demande s'il est possible d'être trop prescriptif à ce sujet, en particulier pour le public plus général. Ceci est un bel exemple - les nombres désignent des pourcentages dont on peut se souvenir, ce qui supprime le besoin d'une échelle que les lecteurs moins alphabétisés en numérique pourraient trouver moins accessible?
geotheory

Réponses:

193

Les ggplot 2.2.0étiquettes From peuvent être facilement empilées en utilisant position = position_stack(vjust = 0.5)in geom_text.

ggplot(Data, aes(x = Year, y = Frequency, fill = Category, label = Frequency)) +
  geom_bar(stat = "identity") +
  geom_text(size = 3, position = position_stack(vjust = 0.5))

entrez la description de l'image ici

Notez également que « position_stack()et position_fill()maintenant empiler les valeurs dans l'ordre inverse du regroupement, ce qui fait que l'ordre de pile par défaut correspond à la légende».


Réponse valable pour les anciennes versions de ggplot:

Voici une approche, qui calcule les points médians des barres.

library(ggplot2)
library(plyr)

# calculate midpoints of bars (simplified using comment by @DWin)
Data <- ddply(Data, .(Year), 
   transform, pos = cumsum(Frequency) - (0.5 * Frequency)
)

# library(dplyr) ## If using dplyr... 
# Data <- group_by(Data,Year) %>%
#    mutate(pos = cumsum(Frequency) - (0.5 * Frequency))

# plot bars and add text
p <- ggplot(Data, aes(x = Year, y = Frequency)) +
     geom_bar(aes(fill = Category), stat="identity") +
     geom_text(aes(label = Frequency, y = pos), size = 3)

Graphique résultant

Ramnath
la source
Merci pour cette réponse. Je l'ai utilisé pour faire la même chose en utilisant data.tableau lieu de plyr, donc quelque chose comme ceci:Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]
atomicules
Est-il possible d'ajouter le total de fréquences aussi?
Pablo Olmos de Aguilera C.
26

Comme hadley l'a mentionné, il existe des moyens plus efficaces de communiquer votre message que les étiquettes dans les graphiques à barres empilées. En fait, les graphiques empilés ne sont pas très efficaces car les barres (chaque catégorie) ne partagent pas un axe, la comparaison est donc difficile.

Il est presque toujours préférable d'utiliser deux graphiques dans ces instances, partageant un axe commun. Dans votre exemple, je suppose que vous souhaitez afficher le total global, puis les proportions de contribution de chaque catégorie au cours d'une année donnée.

library(grid)
library(gridExtra)
library(plyr)

# create a new column with proportions
prop <- function(x) x/sum(x)
Data <- ddply(Data,"Year",transform,Share=prop(Frequency))

# create the component graphics
totals <- ggplot(Data,aes(Year,Frequency)) + geom_bar(fill="darkseagreen",stat="identity") + 
  xlab("") + labs(title = "Frequency totals in given Year")
proportion <- ggplot(Data, aes(x=Year,y=Share, group=Category, colour=Category)) 
+ geom_line() + scale_y_continuous(label=percent_format())+ theme(legend.position = "bottom") + 
  labs(title = "Proportion of total Frequency accounted by each Category in given Year")

# bring them together
grid.arrange(totals,proportion)

Cela vous donnera un affichage à 2 panneaux comme celui-ci:

Graphique à 2 panneaux empilés verticalement

Si vous souhaitez ajouter des valeurs de fréquence, un tableau est le meilleur format.

AndrewMinCH
la source