-2

My data looks like

    language    tone        count   tone_percent    label_pos   pos
1   c           positive    3460    36.16977        18.08488    7
2   c           neutral     2046    21.38825        46.86389    7
3   c           negative    4060    42.44198        78.77901    7
4   c#          positive    3732    41.26949        20.63475    3
5   c#          neutral     1832    20.25876        51.39887    3
6   c#          negative    3479    38.47175        80.76413    3
7   c++         positive    3136    33.13960        16.56980    8
8   c++         neutral     2008    21.21949        43.74934    8
9   c++         negative    4319    45.64092        77.17954    8

And I have been trying to visualize them by using ggplot2 bar chart:

p <-ggplot() + theme_bw() + geom_bar(aes(y=tone_percent, x=reorder(language, -pos), fill=tone), data=data, stat="identity") + 
  geom_text(data=data, aes(x = language, y = label_pos, ymax=label_pos, hjust = 0.5, label = paste0(round(tone_percent),"%")), size=4) + 
  labs(x="Language", y="Percentage of tone") +
  scale_fill_manual(values=c('#F45E5A', '#5086FF', '#17B12B')) + 
  theme(legend.position="bottom", legend.direction="horizontal", legend.title = element_blank()) + coord_flip()

and it gives almost excellent result: enter image description here

However, the legend shows the labels in alphabetical order, but I would like to display them in the same order as bars are drawn in the chart : Positive then Neutral then Negative

Is there any way to achieve that?

sovo2014
  • 487
  • 7
  • 17
  • That's not a good dupe; that approach would change the color order of the bars as well, so they still wouldn't line up with the legend. – alistaire Feb 18 '17 at 08:52

2 Answers2

4

You can pass the guides parameter of the scale functions guide_legend(reverse = TRUE), which will reverse the legend order without reordering the bars. Cleaned up a bit:

ggplot(data, aes(x = reorder(language, -pos), y = tone_percent, fill = tone)) + 
    geom_col() + 
    geom_text(aes(y = label_pos, label = paste0(round(tone_percent),"%"))) + 
    coord_flip() + 
    labs(x = "Language", y = "Percentage of tone") +
    scale_fill_manual(NULL, values=c('#F45E5A', '#5086FF', '#17B12B'), 
                      guide = guide_legend(reverse = TRUE)) + 
    theme_bw() + 
    theme(legend.position = "bottom", 
          legend.direction = "horizontal")

plot with correct legend

alistaire
  • 42,459
  • 4
  • 77
  • 117
0

You need to format the tone variable as a factor.

data$tone <- factor(data$tone, levels=c("positive", "neutral", "negative"))

Karthik Arumugham
  • 1,300
  • 1
  • 11
  • 18
  • Thanks, but "tone" is actually the factor, I checked that: > str(data) 'data.frame': 9 obs. of 6 variables: $ language : Factor w/ 8 levels "c","c#","c++",..: 1 1 1 2 2 2 3 3 3 $ tone : Factor w/ 3 levels "negative","neutral",..: 3 2 1 3 2 1 3 2 1 $ count : int 3460 2046 4060 3732 1832 3479 3136 2008 4319 $ tone_percent: num 36.2 21.4 42.4 41.3 20.3 ... $ label_pos : num 18.1 46.9 78.8 20.6 51.4 ... $ pos : int 7 7 7 3 3 3 8 8 8 – sovo2014 Feb 18 '17 at 09:15
  • @sovo2014 You need to format it by specifying the levels to control the order. Check `levels(data$tone)` – Karthik Arumugham Feb 18 '17 at 09:29