How to reliably place text labels next to dots of different sizes in ggplot2?

I am trying to make a marked portion of a bubble with ggplot2in R. Here is a simplified scenario:

I have a data frame with the 4 variables: 3 quantitative variables x, yand zwhile the other variable that refers to the point lab.

I want to create a scatter plot where the position is determined by xand y, and the size of the points is determined z. Then I want to place text labels next to the dots (for example, to the right of the dot) without overlapping the text on top of the dot.

If the points did not change in size, I could just change the aesthetics of the layer geom_textby adding a scaling constant (for example, aes(x=x+1, y=y+1)). However, even in this simple case, I have a problem with the correct position of the text, because the points do not scale with the output dimensions of the graph. In other words, the size of the points remains constant on the 500x500 and 1000x1000 sections - they do not scale with the dimensions of the plotted plot.

Therefore, I think that I need to scale the position of the label according to the size (for example, dimension) of the output graph, or I need to somehow get the radius of the points from ggplotand shift my text labels. Is there any way to do this in ggplot2?

Here is the code:

# Stupid data
df <- data.frame(x=c(1,2,3), 
                 y=c(1,2,3), 
                 z=c(1,2,1),
                 lab=c("a","b","c"), stringsAsFactors=FALSE)

# Plot with bad label placement
ggplot(aes(x=x, y=y), data=df) + 
  geom_point(aes(size=z)) + 
  geom_text(aes(label=lab), 
            colour="red") +
  scale_size_continuous(range=c(5, 50), guide="none")

: , hjust vjust geom_text, .

# Trying hjust and vjust, but it doesn't look nice
ggplot(aes(x=x, y=y), data=df) + 
  geom_point(aes(size=z)) + 
  geom_text(aes(label=lab), hjust=0, vjust=0.5, 
            colour="red") +
  scale_size_continuous(range=c(5, 50), guide="none")

EDIT: , , . , - .

, : , . ​​ . , (, - ) , . position_jitter, , .

+4
3

, _ *** , , . GeomText, , kludgy ,

enter image description here

geom_shiftedtext <- function (mapping = NULL, data = NULL, stat = "identity", 
                       position = "identity", 
                       parse = FALSE, ...) { 
  GeomShiftedtext$new(mapping = mapping, data = data, stat = stat, position = position, 
               parse = parse, ...)
}
require(proto)
GeomShiftedtext <- proto(ggplot2:::GeomText, {
  objname <- "shiftedtext"
  draw <- function(., data, scales, coordinates, ..., parse = FALSE, na.rm = FALSE) {
    data <- remove_missing(data, na.rm, 
                           c("x", "y", "label"), name = "geom_shiftedtext")

    lab <- data$label
    if (parse) {
      lab <- parse(text = lab)
    }

    with(coord_transform(coordinates, data, scales),
         textGrob(lab, unit(x, "native") + unit(0.375* size, "mm"), 
                  unit(y, "native"), 
                  hjust=hjust, vjust=vjust, rot=angle, 
                  gp = gpar(col = alpha(colour, alpha), 
                            fontfamily = family, fontface = fontface, lineheight = lineheight))

         )
  }

})


df <- data.frame(x=c(1,2,3), 
                 y=c(1,2,3), 
                 z=c(1.2,2,1),
                 lab=c("a","b","c"), stringsAsFactors=FALSE)

ggplot(aes(x=x, y=y), data=df) + 
  geom_point(aes(size=z), shape=1) + 
  geom_shiftedtext(aes(label=lab, size=z),
            hjust=0, colour="red") +
  scale_size_continuous(range=c(5, 100), guide="none")
+3

, , x , z.

ggplot(aes(x=x, y=y), data=df) + 
    geom_point(aes(size=z)) + 
    geom_text(aes(label=lab, x = x + .06 + .14 * (z - min(z))), 
              colour="red") +
    scale_size_continuous(range=c(5, 50), guide="none")

, , . x = x + .05 + 0 * (z-min(z)) , , , .

+1

. , , .

dodge <- abs(scale(df$z))/4

ggplot(data = df, aes(x = x, y = y)) + 
  geom_point(aes(size = z)) +
  geom_text(aes(x = x + dodge), label = df$lab, colour = "red") +
  scale_size_continuous(range = c(5, 50), guide = "none")

Update Just tried position_jitter, but the argument widthtakes only one value, so right now I'm not sure how useful this function will be. But I would be glad to find that I'm wrong. An example with another small dataset:

df3 <- mtcars[1:10, ]
ggplot(data = df3, aes(x = wt, y = mpg)) +
  geom_point(aes(size = qsec), alpha = 0.1) +
  geom_text(label = df3$carb, position = position_jitter(width = 0.1, height = 0)) +
  scale_size_continuous(range = c(5, 50), guide = "none")
+1
source

All Articles