Mostrando valores de datos en un gráfico de barras apiladas en ggplot2

112

Me gustaría mostrar valores de datos en un gráfico de barras apiladas en ggplot2. Aquí está mi código intentado

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") 

ingrese la descripción de la imagen aquí

Me gustaría mostrar estos valores de datos en el medio de cada parte. Cualquier ayuda en este asunto será muy apreciada. Gracias

MYaseen208
fuente
Pregunta relacionada: stackoverflow.com/questions/18994631/…
Tyler Rinker
No es realmente el lugar para un debate, pero me pregunto si es posible ser demasiado prescriptivo sobre esto, particularmente para la audiencia más general. Este es un buen ejemplo : los números denotan porcentajes que se pueden recordar, lo que elimina la necesidad de una escala que los lectores con menos conocimientos numéricos podrían encontrar menos accesible.
geoteoría

Respuestas:

193

Desde ggplot 2.2.0etiquetas se pueden apilar fácilmente usando position = position_stack(vjust = 0.5)en 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))

ingrese la descripción de la imagen aquí

También tenga en cuenta que " position_stack()y position_fill()ahora apila los valores en el orden inverso de la agrupación, lo que hace que el orden de pila predeterminado coincida con la leyenda".


Respuesta válida para versiones anteriores de ggplot:

Aquí hay un enfoque, que calcula los puntos medios de las barras.

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)

Gráfico resultante

Ramnath
fuente
Gracias por esta respuesta. Lo usé para hacer un uso similar en data.tablelugar de plyr, así que algo como esto:Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]
atomicules
¿Hay alguna forma de agregar la frecuencia total también?
Pablo Olmos de Aguilera C.
26

Como mencionó Hadley, hay formas más efectivas de comunicar su mensaje que las etiquetas en gráficos de barras apiladas. De hecho, los gráficos apilados no son muy efectivos ya que las barras (cada categoría) no comparten un eje, por lo que la comparación es difícil.

Casi siempre es mejor usar dos gráficos en estos casos, compartiendo un eje común. En su ejemplo, supongo que desea mostrar el total general y luego las proporciones que contribuyó cada categoría en un año determinado.

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)

Esto le dará una pantalla de 2 paneles como esta:

Gráfico de 2 paneles apilado verticalmente

Si desea agregar valores de frecuencia, una tabla es el mejor formato.

AndrewMinCH
fuente