2

I am trying to adjust x and ymax in the following script in ggplot2 package in R to adjust plotting coordinates of errorbar, however it returns errors.

  gplot <- function(prd) {

        ggplot() +
        geom_polygon(data=shp.t,aes(x=long,y=lat,group=group),
                      fill="white",colour="grey") +
        ## Plot errorbar
        geom_errorbar(data=te10.cent,size=2,colour="red",
                      alpha=.8,width=0,
                      aes_(x=quote(long.cent)-350,ymin=quote(lat.cent),       
                                 ymax=quote(lat.cent)+prd))
        }
gplot("Field Name") # Not number but field name of the data frame

(Sorry, I cannot upload the actual data frame that I am using.)

These are the errors that I am facing:

Error in quote(lat.cent) + prd * .pt : non-numeric argument to binary Operator
Error in quote(lat.cent)+prd * .pt : non-numeric argument to binary Operator

It works in both cases if -350 and +prd are omitted from the script or using 'aes' with actual variable in the data frame. I tried other scripts; "long.cent"-350 and "lat.cent"+prd instead of the above script, however it also returns the same error.

I searched for solutions but all of them explains how to use aes_ without mixing argument and arithmetic calculation. I need to mix non-standard expression with arithmetic calculation to adjust my plot but how?

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104
HSJ
  • 687
  • 6
  • 16
  • 1
    Have you tried using `scale_x_continuous` / `scale_y_continuous` or `coord_cartesian`? See this post https://stackoverflow.com/questions/3606697/how-to-set-limits-for-axes-in-ggplot2-r-plots – Ben G Jun 11 '18 at 13:26
  • 1
    Can you create a reproducible example e.g. on one of the build in datasets such as cars or iris? – Esben Eickhardt Jun 11 '18 at 13:27
  • Thank you for both of your suggestions, it worked out thanks to @missuse 's solutions. – HSJ Jun 11 '18 at 14:43

2 Answers2

3

I trust this will resolve your issue:

gplot <- function(prd) {

  ggplot() +
    geom_polygon(data = shp.t,
                 aes_(x = ~long,
                      y = ~lat,
                      group = ~group),
                 fill = "white",
                 colour = "grey") +
    ## Plot errorbar
    geom_errorbar(data = te10.cent,
                  size = 2,
                  colour = "red",
                  alpha = .8,
                  width = 0,
                  aes_(x = ~long.cent - 350,
                       ymin = ~lat.cent,       
                       ymax = ~lat.cent + prd))
}

reproducible example:

some data:

library(tidyverse)

data(iris)

iris %>%
  group_by(Species) %>%
  summarise_all(~mean(.)) -> summed_iris

gplot <- function(prd){
  ggplot(summed_iris) +
    geom_col(aes_(x = ~Species,
                  y = ~Sepal.Length))+
    geom_errorbar(aes_(x = ~Species,
                       ymin = ~Sepal.Length -prd,
                       ymax = ~Sepal.Length + prd))

}

gplot(0.5)

enter image description here

EDIT: to the question in the comment:

In the case when prd is the column name of the data perhaps it is best to precompute the values:

gplot <- function(prd){
  ymin <-  with(summed_iris, get("Sepal.Length") - get(prd))
  ymax <-  with(summed_iris, get("Sepal.Length") + get(prd))
  summed_iris <- data.frame(summed_iris, ymin, ymax)
  ggplot(summed_iris) +
    geom_col(aes_(x = ~Species,
                  y = ~Sepal.Length))+
    geom_errorbar(aes_(x = ~Species,
                       ymin = ~ymin,
                       ymax = ~ymax))

}
gplot("Petal.Length")

enter image description here

missuse
  • 19,056
  • 3
  • 25
  • 47
0

With the upcoming ggplot2 2.3.0 (to be released in late June 2018), aes_(...) is soft-deprecated and the recommendation is to use tidy eval. This means in the context here that you write !!prd when you want the content of the variable prd instead of the symbol prd.

library(ggplot2)
library(dplyr)
#> 
#> Attaching package: 'dplyr'
#> The following objects are masked from 'package:stats':
#> 
#>     filter, lag
#> The following objects are masked from 'package:base':
#> 
#>     intersect, setdiff, setequal, union

iris %>%
  group_by(Species) %>%
  summarise_all(~mean(.)) -> summed_iris

gplot <- function(prd){
  ggplot(summed_iris) +
    geom_col(aes(x = Species, y = Sepal.Length)) +
    geom_errorbar(
      aes(x = Species, ymin = Sepal.Length - !!prd, ymax = Sepal.Length + !!prd)
    )
}

gplot(0.5)

And if you want the function gplot() to be able to take symbols just like aes() does, then you need to add an enquo() at the beginning of the function definition. It captures the expression that was provided to the function as well as the enclosing environment.

gplot <- function(prd){
  prd <- enquo(prd)
  ggplot(summed_iris) +
    geom_col(aes(x = Species, y = Sepal.Length)) +
    geom_errorbar(
      aes(x = Species, ymin = Sepal.Length - !!prd, ymax = Sepal.Length + !!prd)
    )
}

gplot(Petal.Length)

scale <- 1/5
gplot(scale*Petal.Length)

Claus Wilke
  • 16,992
  • 7
  • 53
  • 104