简体   繁体   中英

adjust x and y scales for individual facets in facet_grid() to fit geom_text_repel() labels?

I need to manually specify the limits of both the x and y axes for each facet (3 rows and 3 columns) in a facet_grid.

I have 2 categorical factors and a continuous y value (so I'm plotting the catch_ema_thousands on the y axis, with data faceted by redlistCategory (3 levels) and TaxonGroup (3 levels), then coloring the points according to VARIABLE (also 3 levels).

The facet_grid has very uneven numbers of data points and range of y values (0 - 1,700, with most points clustered around 0, and some facets with 20 points and others with 0 or 1).

I have scale_y_sqrt to transform the y axis, which helps, but it's still too hard to see the dots in the busy facets.

I've used the scales = "free" and space="free" arguments in facet_grid() , which adjusts the facet sizes to fit to the data points, but doesn't account for fitting the geom_text_repel() labels.

Do I have to adjust the facet sizes within ggrepel ?

library(scales)
library(ggrepel)
library(forcats)
library(RColorBrewer)
library(tidyverse)

ylimits <- c(2,NA) #keep the labels above the cluster of points at the bottom of the facets

List of ~25 species I want to label:

special.points <- special.points <- rownames(subset(plotdat, 
                         SpeciesOrTaxon %in% c("Gadus morhua","Melanogrammus aeglefinus","Thunnus obesus",
                                            "Trachurus trachurus","Sardinella maderensis","Thunnus thynnus",
                                            "Thunnus maccoyii","Hippoglossus hippoglossus","Squalus acanthias",
                                            "Merluccius senegalensis","Epinephelus striatus","Apostichopus japonicus",
                                            "Mobula mobular","Isurus oxyrinchus","Mustelus schmitti",
                                            "Pseudotolithus senegalensis","Sebastolobus alascanus",
                                            "Leucoraja circularis","Argyrosomus hololepidotus","Raja undulata",
                                            "Isurus paucus","Sphyrna lewini","Squatina argentina","Dipturus batis",
                                            "Squatina squatina","Carcharhinus falciformis","Squalus acanthias",
                                            "Makaira nigricans","Thunnus orientalis","Carcharhinus longimanus",
                                            "Lamna nasus","Sphyrna zygaena","Alopias vulpinus","Cetorhinus maximus",
                                            "Alopias superciliosus","Carcharodon carcharias","Palinurus elephas"))) 

My really annoying plot:

p <- ggplot(data = plotdat, aes(x= -totRank, y = catch_ema_thousands, label = Name_abbrev)) + 
  geom_point(data=plotdat,aes(color = VARIABLE), size = 1.2, shape = 1, stroke = 0.8) +
  scale_color_manual(values=c("black","orange","darkgrey"), labels = c("CITES","Intl trade","No intl trade")) +
  facet_grid(redlistCategory~TaxonGroup, scales = "free", space = "free") + 
  scale_y_sqrt() +
  geom_text_repel(data = plotdat, 
                  aes(x=-totRank, y = catch_ema_thousands, label = Name_abbrev), 
# used the abbreviated species name to try and fit them better
                  segment.color = "black", segment.size = 0.2, segment.alpha = 0.5, 
                  direction = "both",
                  min.segment.length = 0.5,
                  force = 10, size = 2, color = "black",
                  ylim = ylimits) + 
  ylab("Average catch (thousand tonnes)") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x=element_blank(),
        axis.title.x=element_blank(),
        axis.title.y = element_blank(),
        legend.position = "top", 
        legend.title = element_blank(),
        panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black")) 
#dev.off() 

I tried a new package, , but got an error:

devtools::install_github("zeehio/facetscales")
library(facetscales)
scales_y <- list(
  CR = scale_y_sqrt(limits = c(0,50), breaks = c(0,50,10)),
  EN = scale_y_continuous(limits = c(0,50), breaks = c(0,50,10)),
  VU = scale_y_continuous(labels = scientific_format())
)

scales_x <- list(
  'Invertebrates' = scale_x_discrete(limits = c(-50,-40)), # plotting in reverse rank (-59 to 0)
  'Cartilaginous fish' =  scale_x_discrete(limits = c(-59,0)),
  'Bony fish' =  scale_x_discrete(limits = c(-59,0))
)

Then,

facet_grid(redlistCategory~TaxonGroup, scales = list(y=scales_y, x = scales_x))

Something isn't right with overriding the "free" scales in facet_grid(), I get this error:

 Error in match.arg(scales, c("fixed", "free_x", "free_y", "free")) : 'arg' must be NULL or a character vector 

Sample plot data:

plotdat <- dput(structure(list(SpeciesOrTaxon = c("Squatina argentina", "Dipturus batis", 
"Squatina squatina", "Thunnus maccoyii", "Epinephelus striatus", 
"Sphyrna lewini", "Mobula mobular", "Isurus oxyrinchus", "Mustelus schmitti", 
"Pseudotolithus senegalensis", "Sebastolobus alascanus", "Leucoraja circularis", 
"Argyrosomus hololepidotus", "Raja undulata", "Isurus paucus", 
"Thunnus thynnus", "Hippoglossus hippoglossus", "Merluccius senegalensis", 
"Apostichopus japonicus", "Carcharhinus falciformis", "Carcharhinus longimanus", 
"Lamna nasus", "Sphyrna zygaena", "Alopias vulpinus", "Cetorhinus maximus", 
"Alopias superciliosus", "Carcharodon carcharias", "Sardinella maderensis", 
"Galeorhinus galeus", "Pomatomus saltatrix", "Pentanemus quinquarius", 
"Pseudupeneus prayensis", "Nemipterus virgatus", "Pseudotolithus senegallus", 
"Dalatias licha", "Lutjanus campechanus", "Megalops atlanticus", 
"Mola mola", "Mustelus mustelus", "Centrophorus squamosus", "Balistes capriscus", 
"Centrophorus lusitanicus", "Leucoraja fullonica", "Rhomboplites aurorubens", 
"Dentex dentex", "Epinephelus marginatus", "Palinurus elephas", 
"Alosa immaculata", "Carcharhinus plumbeus", "Oxynotus centrina", 
"Gymnura altavela", "Carcharias taurus", "Gadus morhua", "Melanogrammus aeglefinus", 
"Thunnus obesus", "Trachurus trachurus", "Squalus acanthias", 
"Makaira nigricans", "Thunnus orientalis"), Name_abbrev = c("S. argentina", 
"D. batis", "S. squatina", "T. maccoyii", "E. striatus", "S. lewini", 
"M. mobular", "I. oxyrinchus", "M. schmitti", "P. senegalensis", 
"S. alascanus", "L. circularis", "A. hololepidotus", "R. undulata", 
"I. paucus", "T. thynnus", "H. hippoglossus", "M. senegalensis", 
"A. japonicus", "C. falciformis", "C. longimanus", "L. nasus", 
"S. zygaena", "A. vulpinus", "C. maximus", "A. superciliosus", 
"C.carcharias", "S. maderensis", "G. galeus", "P. saltatrix", 
"P. quinquarius", "P. prayensis", "N. virgatus", "P. senegallus", 
"D. licha", "L. campechanus", "M. atlanticus", "M. mola", "M. mustelus", 
"C. squamosus", "B. capriscus", "C. lusitanicus", "L. fullonica", 
"R. aurorubens", "D. dentex", "E. marginatus", "P. elephas", 
"A. immaculata", "C. plumbeus", "O. centrina", "G. altavela", 
"C. taurus", "G. morhua", "M. aeglefinus", "T. obesus", "T. trachurus", 
"S. acanthias", "M. nigricans", "T. orientalis"), redlistCategory = structure(c(1L, 
1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("CR", "EN", 
"VU"), class = "factor"), TaxonGroup = structure(c(2L, 2L, 2L, 
3L, 3L, 2L, 2L, 2L, 2L, 3L, 3L, 2L, 3L, 2L, 2L, 3L, 3L, 3L, 1L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 3L, 2L, 3L, 3L, 3L, 3L, 3L, 2L, 
3L, 3L, 3L, 2L, 2L, 3L, 2L, 2L, 3L, 3L, 3L, 1L, 3L, 2L, 2L, 2L, 
2L, 3L, 3L, 3L, 3L, 2L, 3L, 3L), .Label = c("Invertebrates", 
"Cartilaginous fish", "Bony fish"), class = "factor"), totRank = c(12, 
39, 55, 7, 38, 56, 57, 8, 11, 17, 33, 36, 37, 50, 58, 6, 9, 16, 
51, 15, 27, 30, 43, 45, 49, 52, 53, 5, 13, 14, 19, 20, 22, 23, 
24, 25, 26, 28, 29, 31, 32, 34, 35, 40, 41, 42, 44, 46, 47, 48, 
54, 59, 1, 2, 3, 4, 10, 18, 21), VARIABLE = structure(c(3L, 3L, 
3L, 2L, 2L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 2L, 2L, 2L, 
2L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
3L, 3L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("CITES", "YES", 
"NO"), class = "factor"), catch_ema_thousands = c(3.886654422, 
0.1724791016, 0.00911430205, 10.54412869, 0.174470439, 0.00807692997, 
0.001640665002, 9.424452066, 6.583041893, 2.659608617, 0.2663195953, 
0.2329239555, 0.2219422872, 0.01671489332, 0.0014159872, 13.44830652, 
7.585155675, 2.774650025, 0.01599999, 3.024126379, 0.4539170316, 
0.3113769576, 0.1163730191, 0.1011488649, 0.01681304105, 0.01561369792, 
0.01416268544, 108.778465, 3.822553738, 3.251341729, 2.440669803, 
1.688880545, 1.358903072, 1.100693581, 1.06694699, 0.8025907339, 
0.5465603847, 0.4392502858, 0.3591757093, 0.2919081194, 0.2671983104, 
0.2478545144, 0.2435067011, 0.15794176, 0.1539382418, 0.1226202735, 
0.1079683714, 0.06792588753, 0.03801280875, 0.02357907878, 0.009323075655, 
0.000514006594, 1652.737638, 484.1897672, 397.4311939, 153.0306153, 
7.422144444, 2.459107988, 1.545317165)), row.names = c(NA, -59L
), class = c("spec_tbl_df", "tbl_df", "tbl", "data.frame")))

Edit: adding alternative using scale_y_sqrt(expand = expand_scale) to make more border room within each facet.

If the sqrt transformation makes more sense here, you might consider making more room for labels automatically by using expand_scale . The default in ggplot is to add 5% beyond the range of your data, but increasing this will create more space for labels on all facets.

It might also be worth tweaking or removing the the ylim = ylimits part, since that created some overlapping bunched labels when I first opened the example.

scale_y_sqrt(expand = expand_scale(0.2)) +
geom_text_repel(data = plotdat, 
                aes(x=-totRank, y = catch_ema_thousands, label = Name_abbrev), 
                # used the abbreviated species name to try and fit them better
                segment.color = "black", segment.size = 0.2, segment.alpha = 0.5, 
                direction = "both", nudge_y = 0,
                min.segment.length = 0.5, max.iter = 5000,
                force = 10, size = 2, color = "black") + # w/o ylim part

在此处输入图片说明


First answer:

I think log10 might be an appropriate scaling option here, given the wide range of magnitudes:

p <- ggplot(data = plotdat, aes(x= -totRank, y = catch_ema_thousands, label = Name_abbrev)) + 
  geom_point(data=plotdat,aes(color = VARIABLE), size = 1.2, shape = 1, stroke = 0.8) +
  scale_color_manual(values=c("black","orange","darkgrey"), labels = c("CITES","Intl trade","No intl trade")) +
  facet_grid(redlistCategory~TaxonGroup, scales = "free", space = "free") + 
    scale_y_log10(
      breaks = 10^(-10:10),
      labels = scales::trans_format("log10", scales::math_format(10^.x))
    ) +
    # annotation_logticks(side = "l") +

  geom_text_repel(data = plotdat, 
                  aes(x=-totRank, y = catch_ema_thousands, label = Name_abbrev), 
                  # used the abbreviated species name to try and fit them better
                  segment.color = "black", segment.size = 0.2, segment.alpha = 0.5, 
                  direction = "both", nudge_y = 0,
                  min.segment.length = 0.5, max.iter = 5000,
                  force = 10, size = 2, color = "black") + #, ylim = ylimits) + 
  ylab("Average catch (thousand tonnes)") +
  theme(axis.text.x = element_blank(),
        axis.ticks.x=element_blank(),
        axis.title.x=element_blank(),
        axis.title.y = element_blank(),
        legend.position = "top", 
        legend.title = element_blank(),
        panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
        panel.background = element_blank(), axis.line = element_line(colour = "black")) 

  p

在此处输入图片说明

blank_data <- read_csv("blankdata.csv")  
# must have all the columns that you call in ggplot. 
# Make a row for the minimum and maximum x and y values you want for each facet
p <- ggplot(data = plotdat, aes(x= xvar, y = yvar, label = labelvar)) + 
  geom_jitter(data=plotdat,
              aes(color = colorvar), size = 1.2, shape = 1, stroke = 0.8, width = 
                0.25, height = 0.25) +
  geom_blank(data=blankdata, aes(x =xvar, y = yvar, label = labelvar)) +
  facet_grid(ycategory ~ xcategory, scales = "free", space = "free") + 
  geom_text_repel(data = labelvar, # can subset and only label certain points
                  aes(x=xvar, y = yvar, label = labelvar),
                  segment.color = "black", segment.size = 0.2, segment.alpha = 
                    0.5, 
                  direction = "both", 
                  min.segment.length = 0.5,
                  force = 10, size = 2, color = "black") +
  scale_y_sqrt(expand = expand_scale(mult=c(0.1,0))) + 
  # added extra space (10%) at the bottom of each axis because all the labels were clustered there 
  scale_x_continuous(expand = expand_scale(mult=c(0.1,0.1))) +
  theme_bw()

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