Electrino
Electrino

Reputation: 2890

How to place labels at set coordinates using ggplot in R?

I am trying to manually set the coordinates of the geom_label in ggplot. The problem is that my plot is a circle (not centred at zero)...and Im trying to figure out a way to 'expand' the x & y positions of the labels, so they are pushed out... hopefully the example below will explain what I mean.

Aside: There is a similar answer here... which does work... but Im not exactly sure what is happening in the code for that answer. I was hoping to find a relatively simple solution. Here's my problem.

If I have a data frame that looks like this:

df <- data.frame(
  x = c(5.000000e-01, 8.090170e-01, 1.000000e+00, 1.000000e+00, 8.090170e-01,
        5.000000e-01, 1.909830e-01, 5.836788e-17, 0.000000e+00, 1.909830e-01),
  y = c(1.0000000, 0.9045085, 0.6545085, 0.3454915, 0.0954915, 
        0.0000000, 0.0954915, 0.3454915, 0.6545085, 0.9045085)
)

labels <- paste0("A", 1:10)

And use ggplot to plot:

p <- ggplot(df, aes(x, y)) +
  geom_point() +
  geom_label(aes(label = labels), nudge_y = 0.05) +
  theme_void()
p

This results in plotting a (almost) circle with the labels nudged slightly in the y-direction:circle plot

However, what I'm trying to achieve is the following (which I quickly made in photoshop): circle plot with moved labels

In the second image, the labels have been moved to the outside of the points.

Here is my attempt at a solution (but it doesn't work). I was thinking I could take the coordinates of my point (i.e., x & y) and scale them between -1 and 1 like so:

LmatX <- (-1 - 1) * ((df$x - min(df$x)) / (max(df$x) - min(df$x))) +1
LmatY <- (-1 - 1) * ((df$y - min(df$y)) / (max(df$y) - min(df$y))) +1

Then, if any of the values in LmatX are positive, then I add some value... and if the values of LmatX are negative, I could subtract by the same value. Similarly for LmatY. For example,

LmatX <- ifelse(LmatX > 0, LmatX + 1, LmatX - 1)
LmatY <- ifelse(LmatY > 0, LmatY + 1, LmatY - 1)

However, the above code is wrong... because, at the moment, the zero vales in LmatX and LmatY are being subtracted by one (whereas they should remain zero!). My idea was I could use the values obtained by LmatX and LmatY and multiply (or add... not sure which) to my original df$x and df$y to create a new set of coordinates to place the labels.

Any suggestion as to how I could achieve this?

Upvotes: 0

Views: 788

Answers (1)

Electrino
Electrino

Reputation: 2890

I figured out a solution to this problem. Following on from the method I laid out in the question... I first scale between -1 & 1 (I was scaling incorrectly in the question)

LmatX <- (1 - -1) * ((df$x - min(df$x)) / (max(df$x) - min(df$x))) + -1
LmatY <- (1 - -1) * ((df$y - min(df$y)) / (max(df$y) - min(df$y))) + -1

Then I used a nested ifelse to add or subtract a small value depending if the values of LmatX or LmatY were positive or negative:

newX <- ifelse(LmatX > 0, df$x + 0.05, ifelse(LmatX < 0, df$x - 0.05, df$x))
newY <- ifelse(LmatY > 0, df$y + 0.05, ifelse(LmatY < 0, df$y - 0.05, df$y))

Then I created a new data frame with the coordinates of the labels:

df_2 <- data.frame(newX, newY)

and plot using the new df in geom_label:

p <- ggplot(df, aes(x, y)) +
  geom_point() +
  geom_label(data =  df_2, aes(x = newX, y = newY, label = labels)) +
  theme_void()
p

Which results in: enter image description here

Upvotes: 2

Related Questions