Search code examples
rggplot2ggtern

Is there a way to have non-overlapping data point labels on a ternery plot in R?


I am trying to replicate a chart I found on FiveThirtyEight at https://fivethirtyeight.com/features/how-cable-news-reacted-to-the-cohen-hearing/. This shows a ternery plot where the location of the words in the 3 axis shows the proportion quoted that by that respective network.

I am currently using R, ggplot2 and more importantly ggtern (which I use extensively for ternery plots). However I have never found a way to make data labels on points not overlap. I have always hoped that ggtern would interact with ggrepel but sadly it doesn't (to my knowledge). Is there any way to force these to interact, or find another way of doing this?

Chart shown in link for clarity of what I'm after: FiveThirtyEight ternery example

Example of my chart with words overlapping and looking bad: Bad ternery plot and bad visualization

EDIT Code to create my hideous chart:

    data <- data.frame(word = c("A","random","set","of","words","that","can","hopefully","help","someone","solve","my","issue","of","overlapping","labels","and","make","my","chart","readable","and","a","good","visualization"),
               axis1 = sample(1:100),
               axis2 = sample(1:100),
               axis3 = sample(1:100))

    ggtern(data = data,
        aes(x = axis1, y = axis2, z = axis3, colour = word, label = word)) +
      geom_point(size = 1) +
      geom_text()

Solution

  • Ok, so you want the functionality as in ggrepel package. While ggrepel wont work here you can use position_nudge_tern and check_overlap:

    word = c("A","random","set","of","words","that","can","hopefully","help","someone","solve","my","issue","of","overlapping","labels","and","make","my","chart","readable","and","a","good","visualization")
    col = c("red", "blue", "green", "red", "blue", "green","red", "blue", "green", "red", "blue", "green","red", "blue", "green", "red", "blue", "green","red", "blue", "green", "red", "blue", "green","red")
    
    n  = 25   #Number of Data Points
    nv = 0.1  #Vertical Adjustment
    pn = position_nudge_tern(y=nv,x=-nv/2,z=-nv/2)
    
    data <- data.frame(x = sample(1:25),
                   y = sample(1:25),
                   z = sample(1:25), 
                   label=word)
    
    ggtern(data = data, aes(x = x, y = y, z = z, colour = col, label = word)) +
      geom_point(size = 1) +
      theme_nomask() + #Allow Labels to Spool Over Edges
      geom_text(position=pn,aes(label=word),check_overlap=T, size=5)
    

    Which will give you non-overlapping labels:enter image description here