PHPFixing
  • Privacy Policy
  • TOS
  • Ask Question
  • Contact Us
  • Home
  • PHP
  • Programming
  • SQL Injection
  • Web3.0

Monday, June 27, 2022

[FIXED] How to combine two data frames into one graph where I will have two stacked bars side by side for each class?

 June 27, 2022     bar-chart, ggplot2, graph, r, stacked-bar-chart     No comments   

Issue

I registered here specifically for this purpose.

Basically I have two data frames that have the exact same information but from two different years.

Here the head() of one of the data frames:

species dbh_cm height_m         f plot dbh_m           ba
1       1    0.7     1.34 7.1627066   16 0.007 3.848451e-05
2       3    1.9     1.95 2.0018036   16 0.019 2.835287e-04
3       3    4.0     3.05 0.9120516   16 0.040 1.256637e-03
4       1    3.5     2.27 1.0072122   16 0.035 9.621128e-04
5       3    0.6     1.52 6.9312671   16 0.006 2.827433e-05
6       3    4.2     2.70 0.9406631   16 0.042 1.385442e-03
        volume class     Sp
1 0.0003693754 (0,5] Spruce
2 0.0011067593 (0,5]  Larch
3 0.0034956596 (0,5]  Larch
4 0.0021997474 (0,5] Spruce
5 0.0002978850 (0,5]  Larch
6 0.0035187332 (0,5]  Larch

For plotting the graphs for each of these I used:

ggplot(data=trees_b, aes(x=class, fill = Sp)) + 
  geom_bar(stat = "count") +
  labs( x = "DBH classes [cm]", y = "Number of trees [n]", fill="Species") +
  scale_x_discrete(labels=c("(0,5]" = "2.5","(5,10]" = "7.5", "(10,15]" = "12.5",
                            "(15,20]" = "17.5", "(20,25]" = "22.5", "(25,30]" = "27.5",
                            "(30,35]" = "32.5", "(35,40]" = "37.5", "(40,45]" = "42.5",
                            "(45,50]" = "47.5", "(50,55]" = "52.5", "(55,60]" = "57.5",
                            "(60,65]" = "62.5", "(65,70]" = "67.5","(70,75]" = "72.5",
                            "(75,80]" = "77.5", "(80,85]" = "82.5")) +
  scale_fill_viridis(direction = -1, discrete = T) +
  theme(axis.text.x = element_text( size = 15),
        axis.text.y = element_text (size = 15),
        axis.title = element_text(size = 15),
        legend.text = element_text (size = 15),
        legend.title = element_text (size = 16, face = "bold"))

I know the code is not the cleanest but it worked out perfectly for what I needed and that is this:

enter image description here

Now I want to basically combine the two graphs into one for comparison purposes, is there a way to do that?


Solution

One approach to combine your graphs would be to use faceting. To this end I use dplyr::bind_rows to bind your datasets by row and which makes it easy to add an identifier column to the data which could then be used as faceting variable:

Note: I also added a simple function to compute the class means.

trees_b <- trees_a

trees <- list(a = trees_a, b = trees_b) |>
  dplyr::bind_rows(.id = "id")

library(ggplot2)
library(viridis)
#> Loading required package: viridisLite

class_mean <- function(x) {
  sapply(stringr::str_extract_all(x, "\\d+"), function(x) mean(as.numeric(x)))
}

ggplot(data = trees, aes(x = class, fill = Sp)) +
  geom_bar(stat = "count") +
  labs(x = "DBH classes [cm]", y = "Number of trees [n]", fill = "Species") +
  scale_x_discrete(labels = class_mean) +
  scale_fill_viridis(direction = -1, discrete = T) +
  theme(
    axis.text.x = element_text(size = 15),
    axis.text.y = element_text(size = 15),
    axis.title = element_text(size = 15),
    legend.text = element_text(size = 15),
    legend.title = element_text(size = 16, face = "bold")
  ) +
  facet_wrap(~id)

EDIT As you clarified in your comment you want a stacked and dodged bar chart. One approach to achieve that would be via the "facets that's don't look like facets" trick. The basic idea is to facet by the variable you mapped on x and instead map the faceting variable on x. Afterwards we use some styling via theme options to get rid of the faceting look. For more options have a look at ggplot2 - bar plot with both stack and dodge.

ggplot(data = trees, aes(x = id, fill = Sp)) +
  geom_bar(stat = "count") +
  labs(x = "DBH classes [cm]", y = "Number of trees [n]", fill = "Species") +
  scale_fill_viridis(direction = -1, discrete = T) +
  theme(
    axis.text.x = element_text(size = 15),
    axis.text.y = element_text(size = 15),
    axis.title = element_text(size = 15),
    legend.text = element_text(size = 15),
    legend.title = element_text(size = 16, face = "bold")
  ) +
  facet_wrap(~class, labeller = labeller(class = class_mean), strip.position = "bottom", nrow = 1) +
  theme(strip.placement = "outside", strip.background.x = element_blank(), panel.spacing.x = unit(0, "pt"))

enter image description here

DATA

trees_a <- structure(list(
  species = c(1L, 3L, 3L, 1L, 3L, 3L), dbh_cm = c(
    0.7,
    1.9, 4, 3.5, 0.6, 4.2
  ), height_m = c(
    1.34, 1.95, 3.05, 2.27,
    1.52, 2.7
  ), f = c(
    7.1627066, 2.0018036, 0.9120516, 1.0072122,
    6.9312671, 0.9406631
  ), plot = c(16L, 16L, 16L, 16L, 16L, 16L),
  dbh_m = c(0.007, 0.019, 0.04, 0.035, 0.006, 0.042), ba = c(
    3.848451e-05,
    0.0002835287, 0.001256637, 0.0009621128, 2.827433e-05, 0.001385442
  ), volume = c(
    0.0003693754, 0.0011067593, 0.0034956596, 0.0021997474,
    0.000297885, 0.0035187332
  ), class = c(
    "(0,5]", "(0,5]", "(0,5]",
    "(0,5]", "(0,5]", "(0,5]"
  ), Sp = c(
    "Spruce", "Larch", "Larch",
    "Spruce", "Larch", "Larch"
  )
), class = "data.frame", row.names = c(
  "1",
  "2", "3", "4", "5", "6"
))


Answered By - stefan
Answer Checked By - Marie Seifert (PHPFixing Admin)
  • Share This:  
  •  Facebook
  •  Twitter
  •  Stumble
  •  Digg
Newer Post Older Post Home

0 Comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Total Pageviews

Featured Post

Why Learn PHP Programming

Why Learn PHP Programming A widely-used open source scripting language PHP is one of the most popular programming languages in the world. It...

Subscribe To

Posts
Atom
Posts
Comments
Atom
Comments

Copyright © PHPFixing