0

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?

Star Cha
  • 3
  • 1

1 Answers1

0

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"
))
stefan
  • 90,330
  • 6
  • 25
  • 51
  • Hello stefan, first of all thank you for your feedback. Maybe I did not explain it properly, the code as you gave it works fine and I have now to graphs one by another, but I would like to combine them in the sense that for example I have the bars for class 2.5 one besides the other from 2009 and 2021, and also for the other classes as well, for easier comparison purposes. – Star Cha Apr 13 '22 at 08:22
  • I already was afraid that you would say that. :D Unfortunately stack and dodge is not a default so one needs some hacks to achieve that. I just made an edit to show you one approach. – stefan Apr 13 '22 at 08:49