简体   繁体   中英

Stacked bar plot with nested categorical variables and textured fill in R

I am trying to create a stacked bar plot containing three categorical variables and one discrete variable, where one of the categorical variables is “nested” within another. The “nesting” categorical variable would be visualized by color, and the “nested” categorical variable would be visualized by different textures (hashed lines, dots, etc.). The result would look like the image here: https://i.stack.imgur.com/vVm9q.jpg

I've had 2 main challenges doing this in R: 1) nesting one categorical variable within another, 2) symbolizing categories with textures. The closest solution I've found to “nest” one categorical variable within another is the script below. However, I would be looking to distinguish the category “sex” by texture using ggplot, not outline color. I would also prefer to have the discrete variable on the x-axis rather than the y-axis. This question shows that the “gridSVG” package may be useful, but I'm not sure how to incorporate this with ggplot.

# This  sample dataset is taken from https://stackoverflow.com/questions/31173931/point-plot-with-se-for-3-categorical-1-continuous-variable-in-r:
library(ggplot2)
library(tibble)

df <- tibble(
  mea = rep(c("PO_P", "Melaniz"), each = 6),
  tre = rep(c("a", "a", "b", "b", "c", "c"), 2),
  sex = rep(c("Male", "Female"), 6),
  len = c(10.66154, 10.58077, 10.29200, 10.60000, 10.28519, 10.65185,
          11.47857, 11.71538, 11.70833, 11.50000, 11.62143, 11.89231)
)

ggplot(df, aes(x = factor(mea), y = len, color = sex, fill = tre)) + 
  geom_bar(stat = "identity", size = 2)

Created on 2019-09-04 by the reprex package (v0.3.0)

You can do this with the ggtextures package. However, you'll need appropriate texture images that can tile. Creating such images is beyond the scope of this answer. I'm using simple animal icons here.

library(ggplot2)
library(tibble)
library(magick)
#> Linking to ImageMagick 6.9.9.39
#> Enabled features: cairo, fontconfig, freetype, lcms, pango, rsvg, webp
#> Disabled features: fftw, ghostscript, x11
library(ggtextures) # devtools::install_github("clauswilke/ggtextures")

textures = list(
  Male = image_read_svg("http://steveharoz.com/research/isotype/icons/horse.svg"),
  Female = image_read_svg("http://steveharoz.com/research/isotype/icons/fish.svg")
)

df <- tibble(
  mea = rep(c("PO_P", "Melaniz"), each = 6),
  tre = rep(c("a", "a", "b", "b", "c", "c"), 2),
  sex = rep(c("Male", "Female"), 6),
  len = c(10.66154, 10.58077, 10.29200, 10.60000, 10.28519, 10.65185,
          11.47857, 11.71538, 11.70833, 11.50000, 11.62143, 11.89231)
)

ggplot(df) +
  aes(
    x = mea, y = len, image = sex, fill = tre,
    group = interaction(sex, tre) # determines which variable should be stacked first, sex or tre
  ) + 
  geom_textured_bar(
    stat = "identity",
    img_width = unit(20, "pt") # adjust for appropriate scaling of textures, or remove
  ) +
  scale_image_manual(values = textures) +
  coord_flip() +
  theme(legend.position = "bottom")

Created on 2019-09-04 by the reprex package (v0.3.0)

ggplot doesn't have the texture option, but you can still get what you want using some code-heavy options (some useful links here ). In my opinion, it's too much hassle and I prefer to just facet the plots and compare the results like that (use fill = tre and add facet_wrap(~sex) or vice versa, depending on what is more meaningful to you).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM