Kerry Kuntz
Kerry Kuntz

Reputation: 23

ggrepel does not work in tertiary diagram

I am creating a tertiary plot in a shiny app and the points are in different parts of the plot depending on the selected sites. The labels need to repel when points are overlapping or land on the axis. When I use geom_text_repel the labels disappear, geom_label_repel doesn't work with ggtern. Any alternatives would be appreaciated.

require(ggplot)
require(ggetern)
require(ggrepel)

USDA.LAB <- USDA %>%   dplyr::group_by(Label) %>%   dplyr::summarise(
         Clay = mean(Clay),
         Sand = mean(Sand),
         Silt = mean(Silt))
 
USDA.LAB$Angle = 0 
USDA.LAB$Angle[which(USDA.LAB$Label == 'Loamy Sand')] = -35
 
 df <- data.frame(   HORIZON = c("A", "B"),   Sand = c(5, 5),   Silt =
 c(5, 5),   Clay = c(80, 80) )

base <-  ggplot(data = USDA, aes(y=Clay, x=Sand, z=Silt)) +
  coord_tern(L="x",T="y",R="z") +
  geom_polygon(alpha = 0.75, size = 0.5, color = 'black',
               aes(color=Label, fill=Label)) +
        geom_text(data = USDA.LAB,
            aes(label = Label, angle = Angle),
            color = 'black',
            size = 3.5) +
  theme_rgbw() +
  theme_showsecondary() +
  theme_showarrows() +
  custom_percent("Percent") +
  theme(legend.justification = c(0, 1),
        legend.position      = c(0, 1),
        axis.tern.padding    = unit(0.15, 'npc')) +
  labs(title = 'USDA Textural Classification Chart',
       fill  = 'Textural Class',
       color = 'Textural Class') +  
  geom_point(data=df, size=3) + geom_text(data=df, aes(label = HORIZON), size=4)
 # geom_text_repel(data= df, aes(label = HORIZON), size = 4) +
 # geom_label_repel()  #as it is not an approved geometry (for ternary plots) under the present ggtern package

base

Upvotes: 1

Views: 74

Answers (1)

I_O
I_O

Reputation: 6921

One approach with {ggpp} to retrieve repelled label positions:

  • load libs, create example data:

    library(ggplot2)
    library(ggtern)
    library(ggpp)
    
    d <- data.frame(label = letters[1:3],
                    clay = c(1,1,1),
                    sand = c(1,1,1),
                    silt = c(1,1,2)
    )

  • create and store plot p with jittered and nudged labels:

    p <- d |> 
      ggplot(aes(x = clay, y = sand, z = silt, label = label)) +
      geom_text_s(position = position_jitternudge(width = .1, height = .1,
                                                  seed = 123, x = 0.1,
                                                  direction = "split",
                                                  nudge.from = "jittered")
      )

  • extract the new label coordinates:

    label_coords <- ggplot_build(p)$data[[1]][1:3]

  • combine original data with label coords, plot with ternary coord. system (credits to user101089 for suggesting theme_nomask():

    d |>
      cbind(label_coords) |> 
      ggplot(aes(x = clay, y = sand, z = silt)) +
      geom_point() +
      geom_text(aes(x = x, y = y, z = z, label = 1:3)) +
      coord_tern('x', 'y', 'z') +
      theme_nomask() ## prevent label clipping along axes

ternary plot with jittered and nudged labels

If needed, you can jitter coincident points accordingly.

Upvotes: 3

Related Questions