1

I am following up on the question and problem in this example:

R stacked barchart with aggregate data

To recap, here is the original problem and the rather elegant solution.

D <- as.data.frame(structure(list(Group = c("A", "A", "A", "A", "A", 
"A", "B", "B", "B", "B", "B", "B"
), Education = c("NVQ Level 4 and above", "NVQ Level3", "NVQ Level 2", 
"Below NVQ Level 2", "Other qualification", "No qualification", 
"NVQ Level 4 and above", "NVQ Level3", "NVQ Level 2", "Below NVQ Level 2", 
"Other qualification", "No qualification"), Full.Time = c(47, 
27, 23, 17, 18, 9, 36, 26, 22, 22, 27, 12), PT.16.hours = c(20, 
24, 22, 18, 18, 12, 22, 21, 21, 22, 14, 10), PT.16.hours.1 = c(12, 
11, 10, 11, 13, 5, 24, 25, 25, 20, 16, 12)), .Names = c("Group", 
"Education", "Full.Time", "PT>16.hours", "PT<16.hours")))

The solution is to plot a stacked barchart with the two types of Education (as the facet) is as follows:

library(reshape2)
library(ggplot2)

df <- melt(D)

ggplot(df, aes(x = Education, y = value, fill = variable)) +
geom_bar(stat = "identity") + 
facet_wrap(~ Group)

enter image description here

However, this leads to a faceted situation. I was wondering how I can have a situation with the two barcharts side by side but without the faceting but an overarching label spanning the six columns of education with the group label (in this case A or B).

I can do the following:

df <- data.frame(df, groupsandeducation = interaction(df$Group, df$Education))

ggplot(df, aes(x = groupsandeducation, y = value, fill = variable)) +
geom_bar(stat = "identity") + 
ylab('') +
xlab('') + 
labs(title = '') +
scale_fill_discrete('') +
theme_bw() +
theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1))

This gives me the following figure: enter image description here

Which gets me part of the way. However, I would like to have the following additionally happen.

  1. A half-bar widths's worth of space perhaps between the two sets of barcharts.
  2. The labels on the x-axis markings should have the A. and the B. stripped out.
  3. I would like A to spand the first six bars and B to span the last six bars on the x-axis.

I want it all in a single figure, hence the desire not to have a facet. How does one do this?

[Updated with solution:] Thanks, here is my solution.

out <- melt(D) %>%
    arrange(Group, Education) %>%
    mutate(position = rep(c(seq(from = 0.8, by = 0.4, length = 6), 0.8 + 0.4*5-0.2 + seq(from = 0.8, by = 0.4, length = 6)),
           each = 3))

ggplot(out, aes(x = position, y = value, fill = variable)) +  
geom_bar(stat = "identity", size = 0.5) +
scale_x_continuous(name = "Group", breaks = c(1.8, 4.4), labels = unique(out$Group)) + ylim(c(-20,100)) +
annotate(geom = "text", 
         x = unique(out$position), y = 0, 
         label = rep(as.character(out$Education[3*(1:6)]), times = 2), size = 3, angle = 90, hjust = 1)  + theme_light()

And this is what I got: enter image description here

[Updated:] I am trying to use coord_polar on this in order to reproduce the circular stacked barchart as in this example.

Polar Histogram

with code on github

The function is too complicated for my actual problem and does not have an explanation for why it does what it does anywhere because it is uncommented code written by an expert.

zx8754
  • 52,746
  • 12
  • 114
  • 209
user3236841
  • 1,088
  • 1
  • 15
  • 39
  • 1
    1) The facet solves your half-bar width. 2) The facet solves the x-axis text. 3) You want A columns first, then B columns? This is achieved by facets. What is it you don't like in your facet solution? What do you mean by 'an overarching label spanning six columns'? This is exactly what your facet solution is providing you. – MrGumble Jan 03 '18 at 14:23

2 Answers2

1

All facets do is put a label over each of the six bars, and put some space between them. So I would use facets. You can change the appearance if that is what you want, e.g.

df <- melt(D)

ggplot(df, aes(x = Education, y = value, fill = variable)) +
  geom_bar(stat = "identity") + 
  facet_wrap( ~ Group, strip.position = 'bottom') +
  theme_minimal() +
  theme(axis.text.x = element_text(angle = 45, hjust = 1, vjust = 1))

enter image description here

There are a lot of other adjustments you can make if needed.

Axeman
  • 32,068
  • 8
  • 81
  • 94
  • Thanks! I like this solution, but I wouldl ike to avoid the faceting. Btw, I have no idea who downvoted it. – user3236841 Jan 03 '18 at 13:38
  • 1
    It sounds to me that you want something that looks exactly like facets, i.e. group labels and space between the bars, but you want to avoid the designed solution. You're not explaining the problem you have with facets, it may be solvable. – Axeman Jan 03 '18 at 13:47
  • Thanks! Good point. I am wanting to put this in as a circular stacked barchart. I will add some more explanation to my question. – user3236841 Jan 03 '18 at 14:22
1

Here is my attempt. I went around by changing the x-axis to numeric. My trick was assigning x values to the bars as if the bars are grouped by each level of Education (e.g., Below NVQ Level 2, No qualification, and NVQ Level 2), and dodged by Group. I wrote the following code in order to manipulate the data to achieve this task.

library(reshape2)
library(dplyr)
library(ggplot2)

out <- melt(D) %>%
       arrange(Education, Group) %>%
       mutate(position = rep(c(0.8, 1.2, 1.8, 2.2, 2.8, 3.2, 3.8, 4.2, 4.8, 5.2, 5.8, 6.2),
                         each = 3))

Then, I wrote the following code for the graphic below. I added A and B to the graphic using annotate().

ggplot(out, aes(x = position, y = value, fill = variable)) +  
geom_bar(stat = "identity", size = 0.5) +
scale_x_continuous(name = "Education", breaks = 1:6, labels = unique(out$Education)) +
annotate(geom = "text", 
         x = unique(out$position), y = -5, 
         label = rep(c("A", "B"), length.out = nrow(out) / 3), size = 3) +
theme(axis.text.x = element_text(angle = 45, hjust = 1))

enter image description here

jazzurro
  • 23,179
  • 35
  • 66
  • 76
  • I like this solution and it is almost what I want, but would like to have the "A " in the labels also and not use color, on the outer "strip". – user3236841 Jan 03 '18 at 13:40
  • @user3236841 I think you want to check [this question](https://stackoverflow.com/questions/20571306/multi-row-x-axis-labels-in-ggplot-line-chart) for that. This is all I can do for now with my time limit. Sorry for not being able to assist you more. – jazzurro Jan 03 '18 at 13:50
  • Thank you. I think that you suggestion will help. I will try it. – user3236841 Jan 03 '18 at 14:23
  • @user3236841 Have a look of my update now. I hope this meets your criteria. – jazzurro Jan 03 '18 at 14:54
  • Yes, it does. I would like the A and B switched but I think that I can do that myself, thanks! – user3236841 Jan 03 '18 at 15:02
  • @user3236841 that is surely something you can do by yourself. Good luck. – jazzurro Jan 03 '18 at 15:05