slowkow / ggrepel

:round_pushpin: Repel overlapping text labels away from each other in your ggplot2 figures.
https://ggrepel.slowkow.com
GNU General Public License v3.0
1.21k stars 95 forks source link

Error when min.segment.length=Inf and force=0 #243

Closed aydemiro closed 8 months ago

aydemiro commented 10 months ago

Summary

Setting min.segment.length=Inf and force=0 raises error: Error in if (!point_inside_text && d > 0 && euclid(int, point_int) > min.segment.length && : missing value where TRUE/FALSE needed

Minimum code

label_size = 2
point_size = 1
box_padding = 0.75 
max_overlaps = Inf 
min_segment_length = Inf 
nudge_y = 1
force = 0

p = ggplot(df_res, aes(x=x, y=y, col=col, label=label)) 
p = p + geom_point(size=point_size)
p = p + repel(size=label_size, 
              min.segment.length = min_segment_length,
              box.padding = box_padding,
              max.overlaps = max_overlaps,
              force=force,
              nudge_y=nudge_y,
              mapping=aes(color=label_text_color, fill=label_background),
              show.legend = FALSE)
p

Suggestions

This is my current workaround but I don't know if it can be a permanent solution: I set force to a small value when min.segment.length is Inf and force is 0.

if (is.infinite(min_segment_length) && (force == 0)) force = 0.0000001

Version information

Here is the output from sessionInfo() in my R session: R version 4.3.1 (2023-06-16) Platform: x86_64-apple-darwin20 (64-bit) Running under: macOS Sonoma 14.0

Matrix products: default BLAS: /System/Library/Frameworks/Accelerate.framework/Versions/A/Frameworks/vecLib.framework/Versions/A/libBLAS.dylib LAPACK: /Library/Frameworks/R.framework/Versions/4.3-x86_64/Resources/lib/libRlapack.dylib; LAPACK version 3.11.0

locale: [1] en_US.UTF-8/en_US.UTF-8/en_US.UTF-8/C/en_US.UTF-8/en_US.UTF-8

time zone: America/New_York tzcode source: internal

attached base packages: [1] stats graphics grDevices utils datasets methods base

other attached packages: [1] ggrepel_0.9.3 ggplot2_3.4.2

loaded via a namespace (and not attached): [1] labeling_0.4.2 utf8_1.2.3 R6_2.5.1 tidyselect_1.2.0 farver_2.1.1
[6] magrittr_2.0.3 gtable_0.3.3 glue_1.6.2 tibble_3.2.1 pkgconfig_2.0.3 [11] generics_0.1.3 dplyr_1.1.2 lifecycle_1.0.3 cli_3.6.1 fansi_1.0.4
[16] scales_1.2.1 grid_4.3.1 vctrs_0.6.3 withr_2.5.0 compiler_4.3.1
[21] tools_4.3.1 munsell_0.5.0 pillar_1.9.0 Rcpp_1.0.11 colorspace_2.1-0 [26] rlang_1.1.1

Paste output here
slowkow commented 10 months ago

Could I please ask you to describe what is your goal? Why would you set force=0?

What is the result that you expected to see?

Your example doesn't run, so I shared a new one below that does run. I hope this helps.

library(ggrepel)
#> Loading required package: ggplot2
df <- mtcars
df$x <- mtcars$mpg
df$y <- mtcars$wt
df$col <- mtcars$cyl
df$label <- rownames(mtcars)

p <- ggplot(df, aes(x = x, y = y, col = col, label = label)) 
p <- p + geom_point()
p <- p + geom_text_repel(min.segment.length = Inf, force= 0.01)
p
#> Warning: ggrepel: 3 unlabeled data points (too many overlaps). Consider
#> increasing max.overlaps


p <- ggplot(df, aes(x = x, y = y, col = col, label = label)) 
p <- p + geom_point()
p <- p + geom_text_repel(min.segment.length = Inf, max.iter = 0)
p

Created on 2023-11-07 with reprex v2.0.2

aydemiro commented 10 months ago

Thanks for the quick response. The reason I wanted to set force=0 was that since we are not drawing lines, labels should not be repelled from the data points. I wanted to place them a little above the points, so I set nudge_y=0.1. You may ask why use ggrepel if not repelling from the points. This plot is part of a pipeline and I want to provide the option not to draw lines and place label to a set position. Anyway, I think using a small force value like in your example should work -and this is what my workaround was aiming to do. Feel free to close the issue but if you would like to reproduce the error, adding nudge_y to your example as below should reproduce it.

library(ggrepel)
#> Loading required package: ggplot2
df <- mtcars
df$x <- mtcars$mpg
df$y <- mtcars$wt
df$col <- mtcars$cyl
df$label <- rownames(mtcars)

p <- ggplot(df, aes(x = x, y = y, col = col, label = label)) 
p <- p + geom_point()
p <- p + geom_text_repel(min.segment.length = Inf, force=0, nudge_y=0.1)
p
slowkow commented 10 months ago

labels should not be repelled from the data points

We can achieve zero repulsion by setting max.iter = 0, as shown in my second example above. This instructs the code to run zero iterations of the repulsion-attraction physical simulation.

In other words, we can expect to see the same output for p + geom_text_repel(max.iter=0) and p + geom_text(). Does that meet your needs?

aphalo commented 10 months ago

@slowkow Maybe the code of the repulsive geoms could be edited so to that max.iter = 0 will be set automatically when force == 0.

aydemiro commented 10 months ago

labels should not be repelled from the data points

We can achieve zero repulsion by setting max.iter = 0, as shown in my second example above. This instructs the code to run zero iterations of the repulsion-attraction physical simulation.

In other words, we can expect to see the same output for p + geom_text_repel(max.iter=0) and p + geom_text(). Does that meet your needs?

Yes, this works too. I didn't know max.iter=0 would have this affect. It is also working nicely with nudge_y>0 as long as I don't also set force=0, which is of course not needed anymore.

slowkow commented 10 months ago

@slowkow Maybe the code of the repulsive geoms could be edited so to that max.iter = 0 will be set automatically when force == 0.

Good idea!

slowkow commented 8 months ago

I think the bug is fixed, but let me know if you run into further issues.

library(ggrepel)
#> Loading required package: ggplot2
df <- mtcars
df$x <- mtcars$mpg
df$y <- mtcars$wt
df$col <- mtcars$cyl
df$label <- rownames(mtcars)

# Error is gone
p <- ggplot(df, aes(x = x, y = y, col = col, label = label))
p <- p + geom_point()
p + geom_text_repel(min.segment.length = Inf, force = 0, nudge_y = 0.1)

Created on 2024-01-05 with reprex v2.0.2