简体   繁体   中英

R - S3 Methods - Plotting

I am tasked with writing an S3 method that plots two graphs where

  1. The user chooses colours for lines in graph 1.
  2. The user chooses colours for the maximum in graph 2.
  3. The user can choose if points exist or not.

I am having trouble with 3.

Example data

date <- seq(as.Date("2018/1/1"), as.Date("2018/1/10"), "days")
rain <- sample(x = 0:25, size  = 10)
max <- sample(x = 10:25, size  = 10)
min <- sample(x = 5:15, size  = 10)
example <-  data.frame(date, rain, max, min)
class(example) <- c("Weather", class(example)) 
class(example)

The below replicates my graph. Can someone help me figure out how to add to this code so a user can turn on and off #OPTIONAL POINTS

plot.Weather <- function(x, colpick1, colpick2, colpick3) {

    ##TEMP PLOT
    par(mfrow=c(2,1)) 
    #Plotting maxtp with title
    plot(x[, 1], x[, 3], 
        main = "Temperatures",
        type = "l", frame = FALSE, 
        col = colpick1, 
        xlab = "Date", ylab = expression(paste("Temperature [",degree,"C]")), 
        xlim = c(min(x[, 1]), max(x[, 1])), ylim = c(0,30))
    #Add a second line
    lines(x[, 1], x[, 4], type = "l", col = colpick2, xlab = "date", ylab = "temp")+
    #Verical dotted lines
    abline(v =x[, 1], lty=3, col="grey")

    #OPTIONAL POINTS
    ##Adding max and min points
    points(x[, 1][which.max(x[, 3])], max(x[, 3]), col = colpick1, pch = 20 ) 
    points(x[, 1][which.min(x[, 4])], min(x[, 4]), col = colpick2, pch = 20 ) 
    #adding text
    text(x[, 1]+0.5, x[, 3]+1, labels = ifelse(x[, 3] == max(x[, 3]), 'Max', NA ), cex= 0.9) 
    text(x[, 1]-0.5, x[, 4]-1, labels = ifelse(x[, 4] == min(x[, 4]), 'Min', NA ), cex= 0.9)



    ##RAINPLOT
    #Plotting maxtp with title
      plot(x[, 1], x[, 2], 
      type = "h", frame = FALSE, 
      col = ifelse(x[, 2] == max(x[, 2]), colpick3, "green"), 
      xlab = "Date", ylab = "Percipitation", 
      xlim = c(min(x[, 1]), max(x[, 1])), ylim = c(0,25))

  }

plot.Weather(example, "red", "blue", "red")

Thanks in advance,

Sean

There might be a much more efficient way than this but I'll give it a shot. Can you just create new columns which exclude values and plot those?

library(tidyverse)
example_options <- example %>% 
  mutate(min_exclude = ifelse(min >= 13, "NA", min),
         max_exclude = ifelse(max >= 10, "NA", max),
         rain_exclude = ifelse(rain>= 12, "NA", rain))

plot(example_options$min_exclude)
plot(example_options$min)

"NA" values have not been plotted and you can change the ifelse conditions to choose the data points you want to leave out.

The above code can be completed with the case_when function instead of ifelse if you want to go pure tidyverse and here is a base r solution for the same thing:

example_options_1 <- example
example_options_1$min_exclude = ifelse(example$min >= 13, "NA", min)
example_options_1$max_exclude = ifelse(example$max >= 10, "NA", max)
example_options_1$rain_exclude = ifelse(example$rain >= 12, "NA", rain)
example_options_1

Or you could take a function approach like this:

options_func <- function(df, col_no, row_no){
  df[row_no, col_no] <- "NA"
  df
}
example2 <- options_func(df = example, col_no = c("min"), row_no = c(3,5))
example2

Here you can select the variable(s) or column position(s) col_no = "min" or col_no = c("min", "max") , col_no = c(3,4) , and row positions and replace them with "NA" . Function could be made more versatile if needed.

Cheers!

I see what you want to do now I think. How about this?:

plot.Weather <- function(x, colpick1, colpick2, colpick3, options = "YES") {

  ##TEMP PLOT
  par(mfrow=c(2,1)) 
  #Plotting maxtp with title
  plot(x[, 1], x[, 3], 
       main = "Temperatures",
       type = "l", frame = FALSE, 
       col = colpick1, 
       xlab = "Date", ylab = expression(paste("Temperature [",degree,"C]")), 
       xlim = c(min(x[, 1]), max(x[, 1])), ylim = c(0,30))
  #Add a second line
  lines(x[, 1], x[, 4], type = "l", col = colpick2, xlab = "date", ylab = "temp")+
    #Verical dotted lines
    abline(v =x[, 1], lty=3, col="grey")

  if (options == "YES"){
  #OPTIONAL POINTS
  ##Adding max and min points
  points(x[, 1][which.max(x[, 3])], max(x[, 3]), col = colpick1, pch = 20 ) 
  points(x[, 1][which.min(x[, 4])], min(x[, 4]), col = colpick2, pch = 20 ) 
  #adding text
  text(x[, 1]+0.5, x[, 3]+1, labels = ifelse(x[, 3] == max(x[, 3]), 'Max', NA ), cex= 0.9) 
  text(x[, 1]-0.5, x[, 4]-1, labels = ifelse(x[, 4] == min(x[, 4]), 'Min', NA ), cex= 0.9)
  }


  ##RAINPLOT
  #Plotting maxtp with title
  plot(x[, 1], x[, 2], 
       type = "h", frame = FALSE, 
       col = ifelse(x[, 2] == max(x[, 2]), colpick3, "green"), 
       xlab = "Date", ylab = "Percipitation", 
       xlim = c(min(x[, 1]), max(x[, 1])), ylim = c(0,25))

}

plot.Weather(example, "red", "blue", "red")

I've just wrapped your #OPTIONAL POINTS code in an if statement that will execute if options == "YES" in the function arguments. If options = anything other than "YES" it will do nothing. I'll leave the other answer there just in case. Cheers!

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