简体   繁体   中英

Problems passing arguments to ggplot in R script

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 ))

在此处输入图片说明

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.

情节看起来像这样:

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"))

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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM