0

I am currently using position = position_dodge2(preserve = "single") within a geom_bar() function to produce two grouped bar plots, with consistent bar widths regardless of the number of levels within each group. This is working fine. The right and left plots are structured the same way, are prepared as two independent plots, with two different datasets, and than assembled through ggarrange() as a final formatting step. One fix would solve the issue in both plots.

The issue I am having trouble with is when I introduce a geom_text() object. Default settings align all geom_text() objects over the central group axis. I have been able to use position_dodge2(width = x) to move individual labels off that axis, but I am forced to specify a width I am having trouble identifying.

This entire process is run through a for() loop dozens of times, so the width is not something I can simply manually play with until I am satisfied.

EDIT: Sample data and code now provided below.

Data:

# Sample1
Species,Class,count,Per
Acer negundo,Invasive,45,7.142857143
Acer platanoides,Invasive,10,1.587301587
Acer rubrum,Native,5,0.793650794
Fraxinus americana,Native,75,11.9047619
Juglans nigra,Native,5,0.793650794
Picea glauca,Native,5,0.793650794
Prunus avium,Exotic,25,3.968253968
Prunus serotina,Native,25,3.968253968
Quercus macrocarpa,Native,5,0.793650794
Rhamnus cathartica,Invasive,355,56.34920635
Rhus typhina,Native,5,0.793650794
Robinia pseudoacacia,Invasive,5,0.793650794
Salix fragilis,Exotic,10,1.587301587
Tilia americana,Native,40,6.349206349
Ulmus americana,Native,15,2.380952381

# Sample2
Species,Class,count,Per
Acer negundo,Invasive,3,7.5
Acer platanoides,Invasive,10,25
Fraxinus americana,Native,1,2.5
Fraxinus pennsylvanica,Native,1,2.5
Juglans nigra,Native,15,37.5
Prunus avium,Exotic,1,2.5
Prunus serotina,Native,2,5
Robinia pseudoacacia,Invasive,3,7.5
Tilia americana,Native,3,7.5
Ulmus americana,Native,1,2.5

Code:

plot1 <- ggplot(sample1, 
                aes(fill=Species, x = Class, y = Per)) +   
  geom_bar(position = position_dodge2(preserve = "single", width = 1.1), stat = "identity") +
  scale_x_discrete(position = "top")  +
  ylab("Proportion of Overstory Trees (%)") +
  xlab("") +
  scale_y_reverse(limits = c(max(mat_data_curr$Per), 0)) +
  coord_flip() +
  ggtitle("Overstory Stocking") +
  geom_text(aes(label = Species, hjust = 1.05), 
            position = position_dodge2(width = mat_dodge),
            fontface = "italic",
            size = 1) +
  scale_fill_manual(values = spp_cols) +
  theme(panel.background = element_rect(fill = 'white', color = 'white'),
        panel.grid.major = element_line(colour = "grey", 
                                        linetype = "dashed", 
                                        linewidth = 0.2),
        legend.position="none",
        axis.text=element_text(size = 6),
        axis.title = element_text(size = 8, face = "bold", margin(t = 10)),
        plot.title = element_text(size = 10, face = "bold"))

plot2 <- ggplot(sample2, aes(fill = Species, x = Class, y = Per)) +   
  geom_bar(position = position_dodge2(preserve = "single", width = 1.1), stat = "identity") +
  geom_text(aes(label = Species, hjust = -0.05), 
            position = position_dodge2(width = 0.9), 
            fontface = "italic", 
            size = 1) +
  scale_y_continuous(limits = c(0, max(mat_data_curr$Per))) +
  coord_flip() +
  ggtitle("Regeneration Stocking") +
  ylab("Proportion of Regeneration (%)") +
  xlab("") +
  scale_fill_manual(values = spp_cols) +
  theme(panel.background = element_rect(fill = 'white', color = 'white'),
        panel.grid.major = element_line(colour = "grey", 
                                        linetype = "dashed", 
                                        linewidth = 0.2),
        legend.position="none",
        axis.text=element_text(size = 6),
        axis.title = element_text(size = 8, face = "bold", margin = margin(t = 10)),
        plot.title = element_text(size = 10, face = "bold", hjust = 1))

plot_comb <- ggarrange(plot1,NA,plot2,nrow=1,ncol=3,widths=c(1,0.05,1)) + 
  annotate('text', x = 0.5, y = 0.5, label = 'Class and Species', size = 4, angle='90', fontface = "bold")

sample of the issue I'm running into.

UnsoughtNine
  • 63
  • 1
  • 8
  • 1
    Could you please provide a reproducible example? – TarJae Jul 29 '23 at 18:02
  • 1
    @TarJae Sure, see the link in the post above. I've taken out everything not related to the issue. The section I have made available for downland is driven through a loop dozens of times, as I've said in the OP. – UnsoughtNine Jul 29 '23 at 18:49
  • 1
    It's always preferable to put example data into the body of the question as code. That way someone could benefit from the Q&A even once the link is dead. And no one needs to download a stranger's link on the internet. – Jon Spring Jul 29 '23 at 21:06
  • @JonSpring Fair enough, code and sample data inserted into the OP. – UnsoughtNine Jul 30 '23 at 04:27

1 Answers1

0

If you're not bound to the specific layout provided (e. g. vertical "Class and species" bar), you could prepare two separate plots (one with reversed scale, the other with inverted axis position), combine them with e. g. {patchwork} and take formatting from there.

Example:

library(ggplot2)
library(dplyr)
library(patchwork)

d <- 
  data.frame(species = c('U. americana', 'T. americana',
                         'A. platanoides', 'A. negundo',
                         'S. fragilis', 'S. alba',
                         'U. americana', 'P. serotina',
                         'R. cathartica', 'A. negundo',
                         'S. fragilis', 'S. alba'),
           class = gl(3, 4, labels = c('native', 'invasive', 'exotic')),
           stocking = gl(2, 1, labels = c('overstory', 'regeneration')),
           prop = runif(12, 10, 100)
           )

## arrange and plot with {patchwork} `+` operator:
p_overstory + p_regeneration 

side-by-side plot with patchwork

I_O
  • 4,983
  • 2
  • 2
  • 15
  • thank you but I think (i) the species will be tricky to read when a group contains a large number, and (ii) you've only shown it here with the same number of species in each group. Are you certain this will work when groups differ in size? I do want all the bars to be the same width between groups, so to my knowledge, I am stuck with position_dodge2(preserve = "single") – UnsoughtNine Jul 29 '23 at 22:42
  • You can enable (and encourage) others to make certain their suggestions play well with your data by providing a minimal reproducible example. The guide right up on top of the R-collective landing page shows how: https://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example – I_O Jul 30 '23 at 07:36
  • I have sample data and code in the original post. – UnsoughtNine Jul 30 '23 at 15:31