Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Too many" of the same value causes an error #13

Closed
mmahmoudian opened this issue Dec 8, 2020 · 4 comments
Closed

"Too many" of the same value causes an error #13

mmahmoudian opened this issue Dec 8, 2020 · 4 comments

Comments

@mmahmoudian
Copy link

mmahmoudian commented Dec 8, 2020

Thanks for the awesome package. The following is the issue I am facing:

When giving the vioplot too many of the same value (and only that value) it produces an error.

These work fine:

> vioplot(x = c(0))
> vioplot(x = c(rep.int(0, 100)))

Adding one order of magnitude and it breaks:

vioplot(x = c(rep.int(0, 1000)))
vioplot(x = c(rep.int(1, 1000)))

The error I get is:

Error in cut.default(x, breaks = breaks) : 'breaks' are not unique

To clarify, if there is even one more number with another value, it will work as intended:

vioplot(x = c(rep.int(c(1), 10000), 2))

My session's info:

R version 4.0.3 (2020-10-10)
Platform: x86_64-pc-linux-gnu (64-bit)
Running under: Manjaro Linux

Matrix products: default
BLAS:   /usr/lib/libopenblasp-r0.3.12.so
LAPACK: /usr/lib/liblapack.so.3.9.0

locale:
 [1] LC_CTYPE=en_US.UTF-8       LC_NUMERIC=C              
 [3] LC_TIME=en_US.UTF-8        LC_COLLATE=en_US.UTF-8    
 [5] LC_MONETARY=fi_FI.UTF-8    LC_MESSAGES=en_US.UTF-8   
 [7] LC_PAPER=fi_FI.UTF-8       LC_NAME=C                 
 [9] LC_ADDRESS=C               LC_TELEPHONE=C            
[11] LC_MEASUREMENT=fi_FI.UTF-8 LC_IDENTIFICATION=C       

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

other attached packages:
[1] vioplot_0.3.5   zoo_1.8-8       sm_2.2-5.6     
[4] beeswarm_0.2.3  varhandle_2.0.5 RCurl_1.98-1.2 
[7] XML_3.99-0.5   

loaded via a namespace (and not attached):
 [1] rstudioapi_0.13 knitr_1.30      magrittr_1.5   
 [4] hms_0.5.3       lattice_0.20-41 R6_2.5.0       
 [7] rlang_0.4.8     highr_0.8       tcltk_4.0.3    
[10] tools_4.0.3     grid_4.0.3      xfun_0.19      
[13] ellipsis_0.3.1  yaml_2.2.1      tibble_3.0.4   
[16] lifecycle_0.2.0 crayon_1.3.4    readr_1.4.0    
[19] vctrs_0.3.4     bitops_1.0-6    compiler_4.0.3 
[22] pillar_1.4.6    pkgconfig_2.0.3
@TomKellyGenetics
Copy link
Owner

Thanks for reporting. I've done some quick testing and it seems to be thresholded at >100. Unclear why this is.

> library("vioplot")
Loading required package: sm
Package 'sm', version 2.2-5.6: type help(sm) for summary information
Loading required package: zoo

Attaching package: ‘zoo’

The following objects are masked from ‘package:base’:

    as.Date, as.Date.numeric

> vioplot(x = c(0))
> vioplot(x = c(rep.int(0, 100)))
> vioplot(x = c(rep.int(0, 500)))
Error in cut.default(x, breaks = breaks) : 'breaks' are not unique
> vioplot(x = c(rep.int(0, 250)))
Error in cut.default(x, breaks = breaks) : 'breaks' are not unique
> vioplot(x = c(rep.int(0, 150)))
Error in cut.default(x, breaks = breaks) : 'breaks' are not unique
> vioplot(x = c(rep.int(0, 100)))
> vioplot(x = c(rep.int(0, 125)))
Error in cut.default(x, breaks = breaks) : 'breaks' are not unique
> vioplot(x = c(rep.int(0, 110)))
Error in cut.default(x, breaks = breaks) : 'breaks' are not unique
> vioplot(x = c(rep.int(0, 101)))
Error in cut.default(x, breaks = breaks) : 'breaks' are not unique
> vioplot(x = c(rep.int(0, 100)))

Is there a particular reason you wish to do this? I can't imagine a use case where plotting all of the same value as a violin would be informative. If you plot multiple groups this does not occur.

> vioplot(x = c(rep.int(0, 100), 1))
> vioplot(x = c(rep.int(0, 100)), y = c(rep.int(0, 100)))
> vioplot(x = c(rep.int(0, 101)), y = c(rep.int(0, 101)))
Error in cut.default(x, breaks = breaks) : 'breaks' are not unique
> vioplot(x = c(rep.int(0, 100)), y = c(rep.int(0, 100), 1))
> vioplot(x = c(rep.int(0, 101)), y = c(rep.int(0, 101)))
Error in cut.default(x, breaks = breaks) : 'breaks' are not unique```

If I can identify the issue we could replace the error by a point making the average (well mean, median, and mode would be the same in this case).

@TomKellyGenetics
Copy link
Owner

This appears to be an issue with a dependency but we could test for the exception in the package.

> options(error = function() {
+     calls <- sys.calls()
+     if (length(calls) >= 2L) {
+         sink(stderr())
+         on.exit(sink(NULL))
+         cat("Backtrace:\n")
+         calls <- rev(calls[-length(calls)])
+         for (i in seq_along(calls)) {
+             cat(i, ": ", deparse(calls[[i]], nlines = 1L), "\n", sep = "")
+         }
+     }
+     if (!interactive()) {
+         q(status = 1)
+     }
+ })
> vioplot(x = c(rep.int(0, 101)), y = c(rep.int(0, 101)))
Error in cut.default(x, breaks = breaks) : 'breaks' are not unique
Backtrace:
1: stop("'breaks' are not unique")
2: cut.default(x, breaks = breaks)
3: cut(x, breaks = breaks)
4: binning.1d(x, y, breaks = breaks, nbins = nbins)
5: binning(x, y, nbins = opt$nbins)
6: h.select(x = x, y = NA, weights = weights, ...)
7: sm.density(c(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
8: do.call("sm.density", c(list(data, xlim = est.xlim), args))
9: vioplot.default(x = c(rep.int(0, 101)), y = c(rep.int(0, 101)))
10: vioplot(x = c(rep.int(0, 101)), y = c(rep.int(0, 101)))```

@mmahmoudian
Copy link
Author

mmahmoudian commented Jan 28, 2021

So this is how I stumbled upon the bug:
I was plotting some RNA-seq read counts for case vs. control for certain genes. I also wanted to add gaps in between each gene (so two violins, gap, two violins, gap, ... two violins). For this, I create the plot as an empty canvas and in every iteration I add two violins and one gap, therefore the violins are plotted one by one and for genes that have value of 0 expression for one group, the vioplot throws the error.

The way I bypassed the error in my code was to add e^-10 to the first lowest number, but of course you cannot do that and instead you can check if there are more than 100 items in the vector, you just trim it to 100 and then plot it.

@TomKellyGenetics
Copy link
Owner

This is corrected in vioplot 0.3.6 on CRAN.

TomKellyGenetics added a commit that referenced this issue Nov 29, 2022
fixed issue discussed for this commit: bd68db3
bug in PR #13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants