Mostrando valores de dados no gráfico de barras empilhadas em ggplot2

112

Eu gostaria de mostrar os valores dos dados no gráfico de barras empilhadas em ggplot2. Aqui está minha tentativa de código

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

insira a descrição da imagem aqui

Eu gostaria de mostrar esses valores de dados no meio de cada porção. Qualquer ajuda nesse sentido será muito apreciada. obrigado

MYaseen208
fonte
Pergunta relacionada: stackoverflow.com/questions/18994631/…
Tyler Rinker
Não é realmente o lugar para um debate, mas me pergunto se é possível ser excessivamente prescritivo sobre isso, especialmente para o público mais geral. Este é um bom exemplo - os números denotam porcentagens que podem ser lembradas, o que elimina a necessidade de uma escala que leitores menos alfabetizados numericamente podem achar menos acessível.
geotheory

Respostas:

193

As ggplot 2.2.0etiquetas podem ser facilmente empilhadas usando position = position_stack(vjust = 0.5)em 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))

insira a descrição da imagem aqui

Observe também que " position_stack()e position_fill()agora empilhe os valores na ordem inversa do agrupamento, o que faz com que a ordem de empilhamento padrão corresponda à legenda."


Resposta válida para versões mais antigas de ggplot:

Aqui está uma abordagem, que calcula os pontos médios das 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
fonte
Obrigado por esta resposta. Usei-o para fazer algo semelhante, usando em data.tablevez de plyr, algo assim:Data.dt[,list(Category, Frequency, pos=cumsum(Frequency)-0.5*Frequency), by=Year]
atomicules
Existe alguma maneira de adicionar a frequência total também?
Pablo Olmos de Aguilera C.
26

Como hadley mencionou, existem maneiras mais eficazes de comunicar sua mensagem do que rótulos em gráficos de barras empilhadas. Na verdade, os gráficos empilhados não são muito eficazes, pois as barras (cada categoria) não compartilham um eixo, por isso a comparação é difícil.

Quase sempre é melhor usar dois gráficos nessas instâncias, compartilhando um eixo comum. Em seu exemplo, estou supondo que você deseja mostrar o total geral e, em seguida, as proporções que cada categoria contribuiu em um determinado ano.

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)

Isso lhe dará uma tela de 2 painéis como esta:

Gráfico de 2 painéis empilhados verticalmente

Se você deseja adicionar valores de frequência, uma tabela é o melhor formato.

AndrewMinCH
fonte