0
votes

I'm trying create a function that will plot measured stream values (as unconnected points), as well as a smooth curve of modeled values. I'd like to be able to make a unique shape for each type of streamflow (15-min vs 24-hour), and also have a unique color and line type for the two model flows.

I have been able to create different colors for my measured values and have that show up correctly in the legend, but when I try to alter the shapes, I get into trouble. Same for trying to match up dashed and solid lines in my curves. I'd tried changing geom_point() + to geom_point(shape = variable) + but that produces this error: Error in layer(data = data, mapping = mapping, stat = stat, geom = GeomLine, : object 'variable' not found

ggplot(data = r1,aes(x=ReturnPeriod, y=value, color=variable)) +
  geom_point()+
  geom_line(data = r2,aes(x=ReturnPeriod, y=value))+
  ylab("Max Yearly Flow (cfs)") +
  xlab("Return Interval (years)") +
  scale_shape_manual(name = "Legend", 
                      labels = c("Obs 15-min", "Obs 24-hour", "15-min P3", "24-hr P3"),
                      values = c("Peak_cfs"=16, "Daily_cfs"=17, "PeakEst"=NA, 
                                 "DailyEst" = NA)) +
  scale_colour_manual(name = "Legend", 
                      labels = c("Obs 15-min", "Obs 24-hour", "15-min P3", "24-hr P3"),
                      values = c("Peak_cfs"="grey", "Daily_cfs"="black", "PeakEst"="dark grey", 
                                 "DailyEst" = "black")) +
  scale_linetype_manual(name = "Legend", 
                        labels = c("Obs 15-min", "Obs 24-hour", "15-min P3", "24-hr P3"),
                        values = c("Peak_cfs"="blank", "Daily_cfs"="blank", "PeakEst"="solid", 
                                   "DailyEst" = "dashed"))+
  guides(colour = guide_legend(override.aes = list(
    linetype = c("blank", "blank", "solid", "dashed"),
    shape = c(16,17,NA,NA),
    color = c("grey","black", "dark grey", "black")))) +
  theme(legend.position=c(0.92, 0.2),  
        legend.background = element_rect(fill="white"),
        legend.key = element_blank(),
        legend.box = "horizontal")

My data is:

r1 = read.table(
  header = TRUE,
  stringsAsFactors = FALSE,
  text = 
"ReturnPeriod  variable value
1      1.090909 Daily_cfs  14.3
2      1.200000 Daily_cfs  52.3
3      1.333333 Daily_cfs  66.6
4      1.500000 Daily_cfs  93.3
5      1.714286 Daily_cfs  94.3
6      2.000000 Daily_cfs 103.0
7      2.400000 Daily_cfs 107.0
8      3.000000 Daily_cfs 119.0
9      4.000000 Daily_cfs 123.0
10     6.000000 Daily_cfs 166.0
11    12.000000 Daily_cfs 207.0
12     1.090909  Peak_cfs  29.0
13     1.200000  Peak_cfs 159.0
14     1.333333  Peak_cfs 241.0
15     1.500000  Peak_cfs 255.0
16     1.714286  Peak_cfs 296.0
17     2.000000  Peak_cfs 320.0
18     2.400000  Peak_cfs 339.0
19     3.000000  Peak_cfs 351.0
20     4.000000  Peak_cfs 512.0
21     6.000000  Peak_cfs 737.0
22    12.000000  Peak_cfs 800.0"
)

r2 <- read.table(
  header = TRUE,
  stringsAsFactors = FALSE,
  text = 
    "ReturnPeriod variable      value
1      1.010101 DailyEst   8.185016
2      2.000000 DailyEst 104.434396
3      4.000000 DailyEst 148.084828
4     10.000000 DailyEst 180.992656
5     25.000000 DailyEst 199.429333
6     50.000000 DailyEst 207.967918
7      1.010101  PeakEst  14.846387
8      2.000000  PeakEst 349.352462
9      4.000000  PeakEst 547.379809
10    10.000000  PeakEst 713.827969
11    25.000000  PeakEst 815.243158
12    50.000000  PeakEst 865.063562"
)

I'm expecting to get triangle symbols for the Obs 24-hour in the graph, instead I'm getting circles, and in both the legend and graph, I'm trying to get the solid black line to be a dashed black line.

Graph produced by current code:

img

2
If you want the linetype to connect to something in the data, you need to specify that inside aes(). Presumably (in your geom_line layer) aes(linetype = variable)Gregor Thomas

2 Answers

0
votes

If you combine r1 and r2 into r3 for plotting and add shape + linetype to aes , it will work

library(ggplot2)

r1$variable <- factor(r1$variable)
r2$variable <- factor(r2$variable)
r3 <- rbind(r1, r2)

ggplot(data = r3, aes(x=ReturnPeriod, y=value, color=variable, shape=variable)) +
  geom_point()+
  geom_line(aes(linetype=variable))+
  ylab("Max Yearly Flow (cfs)") +
  xlab("Return Interval (years)") +
  scale_shape_manual(name = "Legend", 
                     labels = c("Obs 15-min", "Obs 24-hour", "15-min P3", "24-hr P3"),
                     values = c("Peak_cfs"=16, "Daily_cfs"=17, "PeakEst"=NA, 
                                "DailyEst" = NA)) +
  scale_colour_manual(name = "Legend", 
                      labels = c("Obs 15-min", "Obs 24-hour", "15-min P3", "24-hr P3"),
                      values = c("Peak_cfs"="grey", "Daily_cfs"="black", "PeakEst"="dark grey", 
                                 "DailyEst" = "black")) +
  scale_linetype_manual(name = "Legend",
                        labels = c("Obs 15-min", "Obs 24-hour", "15-min P3", "24-hr P3"),
                        values = c("Peak_cfs"="blank", "Daily_cfs"="blank", "PeakEst"="solid",
                                   "DailyEst" = "dashed"))+
  guides(colour = guide_legend(override.aes = list(
    linetype = c("blank", "blank", "solid", "dashed"),
    shape = c(16,17,NA,NA),
    color = c("grey","black", "dark grey", "black")))) +
  theme(legend.position=c(0.8, 0.6),  
    legend.background = element_rect(fill="white"),
    legend.key = element_blank(),
    legend.box = "horizontal")
#> Warning: Removed 12 rows containing missing values (geom_point).

enter image description here

0
votes

You need to tell ggplot how to group the shapes by including geom_point(aes(shape = factor(variable)))

Then you need a values call in scale_shape_manual(values = c(19, 17)) which tells ggplot which symbols to use (in this case filled circles and filled triangles). This should be instead of of the current list you have for values.

Similarly for your geom_line call and the two line types, you need to include a group factor and linetype values.

See some good tips on the ggplot2 pages