Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ggplot2 Vertical Bars Nested in Horizontal Bars [product plot]

Tags:

plot

r

ggplot2

I have a group of data with a factor nested within another factor.

    Family  Member Count
1  family1 Brother     3
2  family2 Brother     1
3  family3 Brother     1
4  family1     Dad     1
5  family2     Dad     1
6  family3     Dad     1
7  family1     Mom     1
8  family2     Mom     1
9  family3     Mom     0
10 family1     Pet     2
11 family2     Pet     0
12 family3     Pet     3
13 family1  Sister     3
14 family2  Sister     5
15 family3  Sister     3

I want to show a horizontal barplot of the parent level and then a vertical barplot of the child level. I came across a Hadley paper outlining how to do this http://vita.had.co.nz/papers/prodplots.pdf. There's initial work he did in a GitHub repo https://github.com/hadley/productplots but due to lack of interest development has stopped. I can use this repo to almost produce what I'm after but not quiet. I'm wondering if anyone can help get the rest of the way there. I know there's other plotting approach but this one is particularly nice because it uses the pre-attentive attribute of comparing lengths with a common zero for counts at both levels of the hierarchy.

Here's what I have from Hadely's repo:

enter image description here

I want to:

  1. remove the extra parent level labels
  2. fill the parent bars with a light color
  3. change the x axis scale to original counts

enter image description here

Here's code that produced the original plot:

devtools::install_github("hadley/productplots")
library(productplots)
library(ggplot2)

dat <- structure(list(Family = c("family1", "family2", "family3", "family1", 
    "family2", "family3", "family1", "family2", "family3", "family1", 
    "family2", "family3", "family1", "family2", "family3"), Member = structure(c(1L, 
    1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L), .Label = c("Brother", 
    "Dad", "Mom", "Pet", "Sister"), class = "factor"), Count = c(3L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 0L, 2L, 0L, 3L, 3L, 5L, 3L)), row.names = c(NA, 
    -15L), .Names = c("Family", "Member", "Count"), class = "data.frame")

dat2 <- dat[rep(1:nrow(dat), dat[["Count"]]), ]


fill <- list(
  aes(fill = Member),
  theme(legend.position = "none"),
  scale_fill_manual(values = c(
    "Dad" = "#2B2D42", 
    "Mom" = "#7A7D7F", 
    "Sister" = "#B1BBCF", 
    "Brother" = "#6E0B21", 
    "Pet" = "#9B4D73", 
    "NA" = "grey50")))

m <- prodplot(dat2, ~ Member + Family, c("hbar", "vbar"), na.rm = TRUE,
         levels = NA) + fill + theme_bw()
m + scale_x_continuous(expand = c(0,0), limits = c(0, 1.1)) +
    theme(panel.grid=element_blank())

I also reproduced the two separate plots if that's of use:

library(ggplot2)

ggplot(dat, aes(Family, weight=Count)) +
    geom_bar(fill="grey80") +
    coord_flip() + 
    scale_y_continuous(expand = c(0,0), limits = c(0, 11)) +
    theme_bw()

ggplot(dat, aes(Family, weight=Count)) +
    geom_bar(aes(fill = Member), position = "dodge") +
    scale_y_continuous(expand = c(0,0), limits = c(0, 6)) +
    theme_bw() +
    facet_wrap(~Family, ncol=1, scales="free_x") +
    theme(text=element_blank(), panel.grid=element_blank())

Other graphics system solutions welcome too.

EDIT Tried to fill like this but made all bars grey not just parent bars:

lvls <- unique(dat[["Family"]])

fill2 <- list(
  aes(fill = Family),
  theme(legend.position = "none"),
  scale_fill_manual(values = setNames(rep("grey90", length(lvls)), lvls)))

m <- prodplot(dat2, ~ Member + Family, c("hbar", "vbar"), na.rm = TRUE,
         levels = NA) + fill + fill2 + theme_bw()
m + scale_x_continuous(expand = c(0,0), limits = c(0, 1.1)) +
    theme(panel.grid=element_blank())
like image 757
Tyler Rinker Avatar asked Aug 27 '15 18:08

Tyler Rinker


1 Answers

How's:

gg <- m + scale_x_continuous(expand = c(0,0), limits = c(0, 1.1), breaks=c(0.0, 0.5, 1.0),
                       labels=c(0, 5, 10)) +
    theme(panel.grid=element_blank())


gb <- ggplot_build(gg)

gt <- ggplot_gtable(gb)

gt$grobs[[4]]$children[[2]]$gp$fill <- "#7f7f7f"

gt$grobs[[2]]$children$axis$grobs[[1]]$label <- gt$grobs[[2]]$children$axis$grobs[[1]]$label[1:3]
gt$grobs[[2]]$children$axis$grobs[[1]]$y <- gt$grobs[[2]]$children$axis$grobs[[1]]$y[1:3]
gt$grobs[[2]]$children$axis$grobs[[2]]$y <- gt$grobs[[2]]$children$axis$grobs[[2]]$y[1:6]

grid.newpage()
grid.draw(gt)

enter image description here

like image 197
hrbrmstr Avatar answered Oct 12 '22 21:10

hrbrmstr