0

I'm trying to figure out what I'm doing wrong passing arguments to ggplot. I've come a long way with existing posts, but have hit a wall here. Probably something stupid, but here goes (I'm leaving out some of the plot formatting since that is not where the problem is):

melted data set "lagres" is the same in both scenarios.

> str(lagres)
 'data.frame':  30 obs. of  4 variables:
  $ ST      : Factor w/ 3 levels 
  $ year    : Factor w/ 6 levels 
  $ variable: Factor w/ 2 levels 
  $ value   : num  

The first plotting call works great:

ggplot(lagres, aes(quarter, value, group = interaction(ERTp, variable), linetype = variable, color = ERTp, shape = variable ))

enter image description here

Trying to convert this to accept arguments and be re-used in a for-loop script does NOT work, even though the structure is really the same:

timevar <- "quarter"
grpvar  <- "ERTp"
fplot       <- function(lagres, timevar, grpvar, ylb, tlb){
plot <- ggplot(lagres, aes_string(x=timevar, y="value", group = interaction("variable", grpvar), linetype = "variable", color = grpvar, shape = "variable")) +
  geom_line(size = 0.5) + geom_point(size = 3) +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) + labs(y = ylb) +
  ggtitle(paste(tlb, grpvar, today, sep = ", ")) +
  theme(plot.title = element_text(lineheight = .8, face = "bold", hjust = 0.5))

fplot(lagres, timevar, grpvar)

Error: geom_path: If you are using dotted or dashed lines, colour, size and linetype must be constant over the line

The problem seems to lie with the "linetype" arg, as removing this results in an appropriate graph in terms of values/colors, but the lines connected wrong and obviously no separate line for each variable/grp.

Plot looks like this:

Trying to analyze the problem further by looking at the structure of the argument, it looks like aes() and aes_string() parse the group interaction differently. Maybe this is the problem. Parsing the "aes()" formulation with raw variables, I get:

> str(aes(quarter, value, group = interaction(ERTp, variable),  linetype = variable, color = ERTp, shape = variable ))
List of 6
 $ x       : symbol quarter
 $ y       : symbol value
 $ group   : language interaction(ERTp, variable)
 $ linetype: symbol variable
 $ colour  : symbol ERTp
 $ shape   : symbol variable

Then, the "aes_string()" method with referenced arguments:

> str(aes_string(timevar, "value", group = interaction(grpvar,  "variable"), linetype = "variable", color = grpvar, shape = "variable" ))
List of 6
 $ group   : Factor w/ 1 level "ST.variable": 1
 $ linetype: symbol variable
 $ colour  : symbol ST
 $ shape   : symbol variable
 $ x       : symbol quarter
 $ y       : symbol value

So, having the group be either a "language interaction" vs. a 1-level factor, would make a difference? Can't figure out what to do about that parsing issue so the group interaction comes out properly. Saw somewhere that "paste()" could be used, but, no, that does not work. Passing ALL arguments (thus, no quoted text in the aes_string() formula) does not help either.

> dput(lagres)
structure(list(ST = structure(c(1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 
3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L, 3L, 1L, 2L, 
3L, 2L, 3L, 1L, 3L, 2L, 3L, 1L, 2L, 3L, 1L, 2L, 3L), .Label =   c("GeraghtyM", 
"Other", "WeenJ"), class = "factor"), quarter = structure(c(1L, 
1L, 1L, 2L, 2L, 2L, 3L, 3L, 3L, 4L, 4L, 4L, 5L, 5L, 5L, 6L, 6L, 
6L, 7L, 7L, 7L, 1L, 2L, 2L, 2L, 3L, 3L, 4L, 4L, 5L, 5L, 6L, 6L, 
6L, 7L, 7L, 7L), .Label = c("2015-Q2", "2015-Q3", "2015-Q4", 
"2016-Q1", "2016-Q2", "2016-Q3", "2016-Q4"), class = "factor"), 
variable = structure(c(1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label =         c("ScanLag", 
"TPADoorToLag"), class = "factor"), value = c(45.3333333333333, 
60.2857142857143, 37.6, 0, 51.375, 95.4166666666667, 26.8, 
42.75, 200, 28, 134, 68.2941176470588, 29, 42.8, 140.7, 0, 
49.2222222222222, 103.833333333333, 0, 20.125, 0, 67.75, 
48, 87, 93, 78, 49.5, 55, 65.6, 83, 59, 54, 153, 114, 111, 
83, 8.66666666666667)), .Names = c("ST", "quarter", "variable", 
"value"), row.names = c(1L, 2L, 3L, 4L, 5L, 6L, 7L, 8L, 9L, 10L, 
11L, 12L, 13L, 14L, 15L, 16L, 17L, 18L, 19L, 20L, 21L, 24L, 25L, 
26L, 27L, 29L, 30L, 31L, 33L, 35L, 36L, 37L, 38L, 39L, 40L, 41L, 
42L), class = "data.frame", na.action = structure(c(22L, 23L, 
28L, 32L, 34L), .Names = c("22", "23", "28", "32", "34"), class =           "omit"))
DocWeen
  • 13
  • 4
  • argh, tried to avoid typos, but the last paragraph should say "livetype" arg, not livetype. Sorry – DocWeen Jan 25 '17 at 20:27
  • auto spell check, I guess: "linetype" – DocWeen Jan 25 '17 at 20:28
  • Please make your question reproducible by including more of the plotting code (like the `geom_path` part of the code) and a small example of your dataset. See [here](http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example) for some examples of how to add data to a question. – aosmith Jan 25 '17 at 21:58
  • Added code and data, HTH, thx! – DocWeen Jan 25 '17 at 23:16

1 Answers1

0

aes_string isn't reading the interaction code that you are using. One way to avoid this is to simply make a new "interaction" variable in your dataset within the function prior to plotting.

For example:

fplot <- function(lagres, timevar, grpvar){
    lagres$combine = interaction(lagres[["variable"]], lagres[[grpvar]])
    plot <- ggplot(lagres, aes_string(x=timevar, y="value", 
                                      group = "combine", linetype = "variable", 
                                      color = grpvar, shape = "variable")) +
        geom_line(size = 0.5) + 
        geom_point(size = 3) 
    plot
}
aosmith
  • 34,856
  • 9
  • 84
  • 118
  • Outstanding! Thanks so much! Shoot me a comment/link, if you can, so I better understand what "language interaction(ERTp, variable)" means and how/why aes parses this in different ways. But, you really helped me out of a hole here. Much appreciated. – DocWeen Jan 26 '17 at 15:18
  • @DocWeen Essentially `aes_string` expects variable names written as character so the entire `interaction` code in `aes_string` would need to be a character. But `interaction` expects non-character variable names. See [here](http://stackoverflow.com/questions/19410781/problems-when-using-ggplot-aes-string-group-and-linetype) for a related question and answers. Also, if my answer helped you solve the problem you can click the check mark next to it. – aosmith Jan 26 '17 at 18:14