ggplot2
ggplot2 copied to clipboard
`geom_raster`can produce an error when aesthetics are set to floating-point values.
When using floating-point values as x/y aesthetics in geom_raster
, I sometimes get the following error (and additional warning):
library(ggplot2)
data_error <- structure(list(bw = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.22222222222222,
1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222,
1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222,
1.22222222222222, 1.44444444444444, 1.44444444444444, 1.44444444444444,
1.44444444444444, 1.44444444444444, 1.44444444444444, 1.44444444444444,
1.44444444444444, 1.44444444444444, 1.44444444444444, 1.66666666666667,
1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667,
1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667,
1.66666666666667, 1.88888888888889, 1.88888888888889, 1.88888888888889,
1.88888888888889, 1.88888888888889, 1.88888888888889, 1.88888888888889,
1.88888888888889, 1.88888888888889, 1.88888888888889, 2.11111111111111,
2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111,
2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111,
2.11111111111111, 2.33333333333333, 2.33333333333333, 2.33333333333333,
2.33333333333333, 2.33333333333333, 2.33333333333333, 2.33333333333333,
2.33333333333333, 2.33333333333333, 2.33333333333333, 2.55555555555556,
2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556,
2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556,
2.55555555555556, 2.77777777777778, 2.77777777777778, 2.77777777777778,
2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778,
2.77777777777778, 2.77777777777778, 2.77777777777778, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3), cutoff = c(0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555555, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555555, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555555, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1), ncomp = c(1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1,
1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), .Names = c("bw", "cutoff",
"ncomp"), class = "data.frame", row.names = c(NA, -100L))
data_ok <- data.frame(expand.grid(bw = seq(1, 3, length.out = 10), cutoff = seq(0,
1, length.out = 10)))
data_ok <- data_ok[order(data_ok$bw, data_ok$cutoff), ]
data_ok[, "ncomp"] <- data_error[, "ncomp"]
row.names(data_error) <- row.names(data_ok) <- NULL
# The two data.frames seem to be equal
all.equal(data_ok, data_error)
#> [1] TRUE
# ...but this produces an error
ggplot(data_error) + geom_raster(aes(x = bw, y = cutoff, fill = ncomp))
#> Warning in f(...): NAs introduced by coercion to integer range
#> Error in matrix(NA_character_, nrow = nrow, ncol = ncol): invalid 'nrow' value (too large or NA)
# ...and this is ok
ggplot(data_ok) + geom_raster(aes(x = bw, y = cutoff, fill = ncomp))
# The problem can be fixed by rounding
ggplot(data_error) + geom_raster(aes(x = round(bw, 10), y = round(cutoff, 10),
fill = ncomp))
Would you mind turning this into a reprex (short for minimal reproducible example)? It's especially helpful for ggplot2, since it automatically generates and uploads the plots (or lack thereof), which makes it much easier to go through at a glance.
If you've never heard of a reprex before, you might want to start by reading the tidyverse.org help page.
Right now the best way to install reprex is:
# install.packages("devtools")
devtools::install_github("tidyverse/reprex")
If you run into problems with access to your clipboard, you can specify an outfile for the reprex, and then copy and paste (or drag and drop) the contents here.
reprex::reprex(input = "fruits_stringdist.R", outfile = "fruits_stringdist.md")
Thanks.
Hello, no problem. Below is the output from reprex()
.
Thanks
library(ggplot2)
data_error <- structure(list(bw = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.22222222222222,
1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222,
1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222,
1.22222222222222, 1.44444444444444, 1.44444444444444, 1.44444444444444,
1.44444444444444, 1.44444444444444, 1.44444444444444, 1.44444444444444,
1.44444444444444, 1.44444444444444, 1.44444444444444, 1.66666666666667,
1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667,
1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667,
1.66666666666667, 1.88888888888889, 1.88888888888889, 1.88888888888889,
1.88888888888889, 1.88888888888889, 1.88888888888889, 1.88888888888889,
1.88888888888889, 1.88888888888889, 1.88888888888889, 2.11111111111111,
2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111,
2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111,
2.11111111111111, 2.33333333333333, 2.33333333333333, 2.33333333333333,
2.33333333333333, 2.33333333333333, 2.33333333333333, 2.33333333333333,
2.33333333333333, 2.33333333333333, 2.33333333333333, 2.55555555555556,
2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556,
2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556,
2.55555555555556, 2.77777777777778, 2.77777777777778, 2.77777777777778,
2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778,
2.77777777777778, 2.77777777777778, 2.77777777777778, 3, 3, 3, 3, 3, 3,
3, 3, 3, 3), cutoff = c(0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555555, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555555, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333,
0.444444444444444, 0.555555555555555, 0.666666666666667, 0.777777777777778,
0.888888888888889, 1), ncomp = c(1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1,
1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)), .Names = c("bw", "cutoff",
"ncomp"), class = "data.frame", row.names = c(NA, -100L))
data_ok <- data.frame(expand.grid(bw = seq(1, 3, length.out = 10), cutoff = seq(0,
1, length.out = 10)))
data_ok <- data_ok[order(data_ok$bw, data_ok$cutoff), ]
data_ok[, "ncomp"] <- data_error[, "ncomp"]
row.names(data_error) <- row.names(data_ok) <- NULL
# The two data.frames seem to be equal
all.equal(data_ok, data_error)
#> [1] TRUE
# ...but this produces an error
ggplot(data_error) + geom_raster(aes(x = bw, y = cutoff, fill = ncomp))
#> Warning in f(...): NAs introduced by coercion to integer range
#> Error in matrix(NA_character_, nrow = nrow, ncol = ncol): invalid 'nrow' value (too large or NA)
# ...and this is ok
ggplot(data_ok) + geom_raster(aes(x = bw, y = cutoff, fill = ncomp))
# The problem can be fixed by rounding
ggplot(data_error) + geom_raster(aes(x = round(bw, 10), y = round(cutoff, 10),
fill = ncomp))
For what it's worth, I am experiencing the same error with the following data.
library(tidyverse)
data = crossing(
x = seq(-1, 1, by = 0.01),
a = seq(1, 5, by = 0.01)
) %>%
mutate(y = a*x^2)
Rounding the variables in the ggplot mapping, as mentioned here, works.
@buggaby Thanks, but it seems your data is not suitable for geom_raster()
, which expects
geom_raster()
is a high performance special case for when all the tiles are the same size.
The error comes from here:
https://github.com/tidyverse/ggplot2/blob/9eae13b3d17bde26cf9df649887b4a6bb2ac92ce/R/geom-raster.r#L72-L79
I found the very small jitterings in data cause NA
.
data_error <- structure(
list(
bw = c(1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222, 1.22222222222222, 1.44444444444444, 1.44444444444444, 1.44444444444444, 1.44444444444444, 1.44444444444444, 1.44444444444444, 1.44444444444444, 1.44444444444444, 1.44444444444444, 1.44444444444444, 1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667, 1.66666666666667, 1.88888888888889, 1.88888888888889, 1.88888888888889, 1.88888888888889, 1.88888888888889, 1.88888888888889, 1.88888888888889, 1.88888888888889, 1.88888888888889, 1.88888888888889, 2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111, 2.11111111111111, 2.33333333333333, 2.33333333333333, 2.33333333333333, 2.33333333333333, 2.33333333333333, 2.33333333333333, 2.33333333333333, 2.33333333333333, 2.33333333333333, 2.33333333333333, 2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556, 2.55555555555556, 2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778, 2.77777777777778, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3),
cutoff = c(0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555555, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555555, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555556, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1, 0, 0.111111111111111, 0.222222222222222, 0.333333333333333, 0.444444444444444, 0.555555555555555, 0.666666666666667, 0.777777777777778, 0.888888888888889, 1),
ncomp = c(1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1)
),
.Names = c("bw", "cutoff", "ncomp"),
class = "data.frame", row.names = c(NA, -100L)
)
a1 <- 1 / 9
data1 <- expand.grid(
x = 1 + 2 * a1 * 0:9,
y = a1 * 0:9,
KEEP.OUT.ATTRS = FALSE
)
data1 <- dplyr::arrange(data1, x, y)
# although they are considered all equal, slightly different
all.equal(data_error$cutoff, data1$y)
#> [1] TRUE
data_error$cutoff - data1$y
#> [1] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [6] 4.440892e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
#> [11] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [16] 4.440892e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
#> [21] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [26] -5.551115e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
#> [31] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [36] 4.440892e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
#> [41] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [46] 4.440892e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
#> [51] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [56] 4.440892e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
#> [61] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [66] 4.440892e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
#> [71] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [76] -5.551115e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
#> [81] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [86] 4.440892e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
#> [91] 0.000000e+00 -1.110223e-16 -2.220446e-16 -3.330669e-16 -4.440892e-16
#> [96] -5.551115e-16 3.330669e-16 3.330669e-16 1.110223e-16 0.000000e+00
Created on 2019-01-10 by the reprex package (v0.2.1)
Since the result of resolution()
is too small, (data1$y - min(data1$y)) / resolution(data1$y, FALSE)
is larger than the max of integer, so as.integer()
returns NA
. I think the resolution must be "rounded" into the range of integer, but I don't have nice idea for now.
library(ggplot2)
a1 <- 1 / 9
data1 <- expand.grid(
x = 1 + 2 * a1 * 0:9,
y = a1 * 0:9,
KEEP.OUT.ATTRS = FALSE
)
data1 <- dplyr::arrange(data1, x, y)
# add some values
data1$y[c(26, 76, 96)] <- data1$y[c(26, 76, 96)] - 9.992007e-16
resolution(data1$y, FALSE)
#> [1] 9.992007e-16
as.integer((data1$y - min(data1$y)) / resolution(data1$y, FALSE))
#> Warning: NAs introduced by coercion to integer range
#> [1] 0 NA NA NA NA NA NA NA NA NA 0 NA NA NA NA NA NA NA NA NA 0 NA NA
#> [24] NA NA NA NA NA NA NA 0 NA NA NA NA NA NA NA NA NA 0 NA NA NA NA NA
#> [47] NA NA NA NA 0 NA NA NA NA NA NA NA NA NA 0 NA NA NA NA NA NA NA NA
#> [70] NA 0 NA NA NA NA NA NA NA NA NA 0 NA NA NA NA NA NA NA NA NA 0 NA
#> [93] NA NA NA NA NA NA NA NA
Created on 2019-01-10 by the reprex package (v0.2.1)
A shot in the dark. At the last step, replace as.integer
with something like:
integerate <- function(x) ifelse(x > .Machine$integer.max, round(x), as.integer(x))
.Machine$integer.max
## [1] 2147483647
integerate(2147483647)
## [1] 2147483647
integerate(2147483648)
## [1] 2147483648
integerate(2147483647.4)
## [1] 2147483647
integerate(2147483647.5)
## [1] 2147483648
It saves us from the errors, but the some part of the raster will get lost then...
We should not shave the raster, but lower the resolution instead. For example:
reso <- max(resolution(data1$y, FALSE),
1 / .Machine$integer.max)
as.integer((data1$y - min(data1$y)) / reso)
But, this is not nice. I believe the cutoff
's reslution should be 0.111111111111111
.
Hi, is there a solution for this error yet? Is there a way to modify my data minimally to avoid the error? Thanks in advance.