tidyverse / ggplot2

An implementation of the Grammar of Graphics in R
https://ggplot2.tidyverse.org
Other
6.48k stars 2.02k forks source link

contour fails when coordinates are not aligned with axes #4320

Open cneyens opened 3 years ago

cneyens commented 3 years ago

Below I have regularly spaced points that are not aligned with the plot axes. I want to plot contour lines but geom_contour seems to fail here. I vaguely remember this used to work in some former ggplot version, but I tried with versions 3.3.2 and 3.3.0 and those also don't plot contours for this data set so I might be wrong... I would expect geom_contour to be able to handle this since the points are fairly regularly spaced (disregarding minor rounding errors from the rotation calculation I've done here).

For context: these could be spatial data points (XY coordinates) placed on a regular grid for which I've obtained several continuous variables, e.g. groundwater levels and chloride concentrations.

library(ggplot2)

df <- expand.grid(x = 1:10,
                  y = 1:10)
df$z <- c(volcano[53:62, 29:38]) # arbitrary

ggplot(df, aes(x = x, y = y)) +
  geom_point() +
  geom_contour(aes(z = z)) +
  coord_fixed()

# rotate points 15 degrees counterclockwise
angle <- atan(df$y/df$x) * 180/pi + 15
df$rotx <- cos(angle * pi/180) * sqrt(df$x^2 + df$y^2)
df$roty <- sin(angle * pi/180) * sqrt(df$x^2 + df$y^2)

p <- ggplot(df, aes(x = rotx, y = roty)) +
  geom_point() +
  coord_fixed()

p + geom_contour(aes(z = z))
#> Warning: stat_contour(): Zero contours were generated
#> Warning in min(x): no non-missing arguments to min; returning Inf
#> Warning in max(x): no non-missing arguments to max; returning -Inf

Created on 2021-01-20 by the reprex package (v0.3.0)

Session info ``` r devtools::session_info() #> - Session info --------------------------------------------------------------- #> setting value #> version R version 4.0.3 (2020-10-10) #> os Windows 10 x64 #> system x86_64, mingw32 #> ui RTerm #> language (EN) #> collate English_Belgium.1252 #> ctype English_Belgium.1252 #> tz Europe/Paris #> date 2021-01-20 #> #> - Packages ------------------------------------------------------------------- #> package * version date lib source #> assertthat 0.2.1 2019-03-21 [1] CRAN (R 4.0.2) #> callr 3.5.1 2020-10-13 [1] CRAN (R 4.0.3) #> cli 2.2.0 2020-11-20 [1] CRAN (R 4.0.3) #> colorspace 2.0-0 2020-11-11 [1] CRAN (R 4.0.3) #> crayon 1.3.4 2017-09-16 [1] CRAN (R 4.0.2) #> curl 4.3 2019-12-02 [1] CRAN (R 4.0.2) #> DBI 1.1.1 2021-01-15 [1] CRAN (R 4.0.3) #> desc 1.2.0 2018-05-01 [1] CRAN (R 4.0.2) #> devtools 2.3.2 2020-09-18 [1] CRAN (R 4.0.3) #> digest 0.6.27 2020-10-24 [1] CRAN (R 4.0.3) #> dplyr 1.0.3 2021-01-15 [1] CRAN (R 4.0.3) #> ellipsis 0.3.1 2020-05-15 [1] CRAN (R 4.0.2) #> evaluate 0.14 2019-05-28 [1] CRAN (R 4.0.2) #> fansi 0.4.2 2021-01-15 [1] CRAN (R 4.0.3) #> farver 2.0.3 2020-01-16 [1] CRAN (R 4.0.2) #> fs 1.5.0 2020-07-31 [1] CRAN (R 4.0.3) #> generics 0.1.0 2020-10-31 [1] CRAN (R 4.0.3) #> ggplot2 * 3.3.3 2020-12-30 [1] CRAN (R 4.0.3) #> glue 1.4.2 2020-08-27 [1] CRAN (R 4.0.3) #> gtable 0.3.0 2019-03-25 [1] CRAN (R 4.0.2) #> highr 0.8 2019-03-20 [1] CRAN (R 4.0.2) #> htmltools 0.5.0 2020-06-16 [1] CRAN (R 4.0.3) #> httr 1.4.2 2020-07-20 [1] CRAN (R 4.0.3) #> isoband 0.2.3 2020-12-01 [1] CRAN (R 4.0.3) #> knitr 1.30 2020-09-22 [1] CRAN (R 4.0.3) #> labeling 0.4.2 2020-10-20 [1] CRAN (R 4.0.3) #> lifecycle 0.2.0 2020-03-06 [1] CRAN (R 4.0.2) #> magrittr 2.0.1 2020-11-17 [1] CRAN (R 4.0.3) #> memoise 1.1.0 2017-04-21 [1] CRAN (R 4.0.2) #> mime 0.9 2020-02-04 [1] CRAN (R 4.0.0) #> munsell 0.5.0 2018-06-12 [1] CRAN (R 4.0.2) #> pillar 1.4.7 2020-11-20 [1] CRAN (R 4.0.3) #> pkgbuild 1.2.0 2020-12-15 [1] CRAN (R 4.0.3) #> pkgconfig 2.0.3 2019-09-22 [1] CRAN (R 4.0.2) #> pkgload 1.1.0 2020-05-29 [1] CRAN (R 4.0.2) #> prettyunits 1.1.1 2020-01-24 [1] CRAN (R 4.0.2) #> processx 3.4.5 2020-11-30 [1] CRAN (R 4.0.3) #> ps 1.5.0 2020-12-05 [1] CRAN (R 4.0.3) #> purrr 0.3.4 2020-04-17 [1] CRAN (R 4.0.2) #> R6 2.5.0 2020-10-28 [1] CRAN (R 4.0.3) #> remotes 2.2.0 2020-07-21 [1] CRAN (R 4.0.3) #> rlang 0.4.10 2020-12-30 [1] CRAN (R 4.0.3) #> rmarkdown 2.6 2020-12-14 [1] CRAN (R 4.0.3) #> rprojroot 2.0.2 2020-11-15 [1] CRAN (R 4.0.3) #> scales 1.1.1 2020-05-11 [1] CRAN (R 4.0.2) #> sessioninfo 1.1.1 2018-11-05 [1] CRAN (R 4.0.2) #> stringi 1.5.3 2020-09-09 [1] CRAN (R 4.0.3) #> stringr 1.4.0 2019-02-10 [1] CRAN (R 4.0.2) #> testthat 3.0.1 2020-12-17 [1] CRAN (R 4.0.3) #> tibble 3.0.5 2021-01-15 [1] CRAN (R 4.0.3) #> tidyselect 1.1.0 2020-05-11 [1] CRAN (R 4.0.2) #> usethis 2.0.0 2020-12-10 [1] CRAN (R 4.0.3) #> vctrs 0.3.6 2020-12-17 [1] CRAN (R 4.0.3) #> withr 2.4.0 2021-01-16 [1] CRAN (R 4.0.3) #> xfun 0.20 2021-01-06 [1] CRAN (R 4.0.3) #> xml2 1.3.2 2020-04-23 [1] CRAN (R 4.0.2) #> yaml 2.2.1 2020-02-01 [1] CRAN (R 4.0.0) #> #> [1] C:/Users/casne/OneDrive/Documenten/R/library_cas #> [2] C:/Program Files/R/R-4.0.3/library ```
clauswilke commented 3 years ago

The requirement for contouring is not that you have a regularly spaced grid but that you have a matrix of z values whose locations can be identified with marginal vectors of x and y values.

See here for a grid that is not regularly spaced:

library(ggplot2)

df <- expand.grid(x = c(1, 2, 4, 8, 16, 32),
                  y = c(1, 2, 4, 8, 16, 32))
df$z <- c(volcano[53:58, 29:34]) # arbitrary

ggplot(df, aes(x = x, y = y)) +
  geom_point() +
  geom_contour(aes(z = z)) +
  coord_fixed()

Created on 2021-01-20 by the reprex package (v0.3.0)

If your input data doesn't have this structure then you may have to force it into this structure via interpolation.

clauswilke commented 3 years ago

(Having said this, it would probably be possible to add this feature to geom_contour(), so I consider this a feature request.)

clauswilke commented 3 years ago

Relevant SO post with a fairly simple solution: https://stackoverflow.com/a/38177092/4975218

Requires an additional dependency on the akima package: https://cran.r-project.org/web/packages/akima/index.html

cneyens commented 3 years ago

Thanks!

I'm aware of multiple SO posts where interpolation is offered as a solution for cases where the starting data set is not gridded, but I was under the impression that the requirement for geom_contour to work was that the data should be (roughly) evenly spaced as stated in the docs. This clears things up for me:

The requirement for contouring is not that you have a regularly spaced grid but that you have a matrix of z values whose locations can be identified with marginal vectors of x and y values.

clauswilke commented 3 years ago

If you feel the documentation is not sufficiently clear, could you open a separate issue just about that?