3

I modified the interactive R Shiny plot from the R Shiny gallery to plot an interactive standard curve. I would like to plot the interactive plot without using ggplot2 library with just using R base plotting functions.

library(ggplot2)

XYdata <- data.frame(cbind(Values = c(91.8, 95.3,   99.8,   123.3,  202.9,  619.8,  1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
                           Concn = c(1000, 300,    100,    30, 10, 3,  1,  0.3,    0.1,    0.03,   0.01,   0)))
ui <- fluidPage(
  fluidRow(
    column(width = 6,
           plotOutput("plot1", height = 350,
                      click = "plot1_click",
                      brush = brushOpts(
                        id = "plot1_brush"
                      )
           ),
           actionButton("exclude_toggle", "Toggle points"),
           actionButton("exclude_reset", "Reset")
    )
  )
)

server <- function(input, output) {
  # For storing which rows have been excluded
  vals <- reactiveValues(
    keeprows = rep(TRUE, nrow(XYdata))
  )
  NonScientific <- function(l) {l <- format(l, scientific = FALSE); parse(text=l)}

  output$plot1 <- renderPlot({
    # Plot the kept and excluded points as two separate data sets

    XYdata <- data.frame(cbind(Values = c(91.8, 95.3,   99.8,   123.3,  202.9,  619.8,  1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
                           Concn = c(1000, 300,    100,    30, 10, 3,  1,  0.3,    0.1,    0.03,   0.01,   0)))
    keep    <- XYdata[ vals$keeprows, , drop = FALSE]
    exclude <- XYdata[!vals$keeprows, , drop = FALSE]
    keep <- subset(keep, Concn > 0)
    exclude <- subset(exclude, Concn > 0)
    nls.fit <- nls(Values ~ (ymax* keep$Concn / (ec50 + keep$Concn)) + Ns*keep$Concn + ymin, data=keep,
                   start=list(ymax=max(keep$Values), ymin = min(keep$Values), ec50 = 3, Ns = 0.2045514))
    keep$nls.pred <- fitted(nls.fit)

    ggplot(keep, aes(y = Values,x = Concn))+geom_point(size = 5,colour="red")+
    geom_smooth(method = "loess",fullrange = F, se = T, aes(Concn, nls.pred),size = 1.5,colour="blue1")+
      geom_point(data = exclude, shape = 21, fill = NA, color = "black",size = 5, alpha = 0.7) +
      xlab('Concentration (nM)')+ ylab('Units')+
      scale_x_log10(labels=NonScientific)+ggtitle("Standard Curve")+theme_classic()+
      theme(panel.background = element_rect(colour = "black", size=1),
            plot.margin = margin(1, 3, 0.5, 1, "cm"), 
            plot.title = element_text(hjust = 0, face="bold",color="#993333", size=16),
            axis.title = element_text(face="bold", color="#993333", size=14),
            axis.text.x = element_text(face="bold", color="#666666", size=12),
            axis.text.y = element_text(face="bold", color="#666666", size=12))
  })

  # Toggle points that are clicked
  observeEvent(input$plot1_click, {
    res <- nearPoints(XYdata, input$plot1_click, allRows = TRUE)

    vals$keeprows <- xor(vals$keeprows, res$selected_)
  })

  # Toggle points that are brushed, when button is clicked
  observeEvent(input$exclude_toggle, {
    res <- brushedPoints(XYdata, input$plot1_brush, allRows = TRUE)

    vals$keeprows <- xor(vals$keeprows, res$selected_)
  })

  # Reset all points
  observeEvent(input$exclude_reset, {
    vals$keeprows <- rep(TRUE, nrow(XYdata))
  })

}

shinyApp(ui, server)

I tried replacing the plotting portion of the script with the following but I am not able to interactively plot. What am I doing wrong here?

 plot(Values ~ Concn, keep, subset = Concn > 0, col = 4, cex = 2, log = "x")
 title(main = "XY Std curve")
 lines(predict(nls.fit, new = list(Concn = Concn)) ~ Concn, keep)
 points(Values ~ Concn, exclude, subset = Concn > 0, col = 1, cex = 2, log = "x")

2 Answers 2

3

You have to add xvarand yvar parameters to nearPoints:

res <- nearPoints(XYdata, input$plot1_click, xvar="Concn", yvar="Values", allRows = TRUE)
Sign up to request clarification or add additional context in comments.

2 Comments

Hi @HubertL, Your suggestion worked. The only issue I am facing now is I am not able to override the axis title with a more detailed one. Can you please have a look at the code below? Whatever I do it writes over the "Concn" and "Values" causing chaos. Any suggestions please?
just add these parameters to the plot call ylab="", xlab=""
0

The working code implementing @HubertL's suggestion for someone like me to use for interactive plotting and to knockout outliers by clicking on or by selecting the point(s) using mouse:

XYdata <- data.frame(cbind(Values = c(91.8, 95.3,   99.8,   123.3,  202.9,  619.8,  1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
                           Concn = c(1000, 300, 100,30, 10, 3,  1,  0.3,    0.1, 0.03, 0.01, 0)))
ui <- fluidPage(
  fluidRow(
    column(width = 6,
           plotOutput("plot1", height = 350,click = "plot1_click", brush = brushOpts(id = "plot1_brush")),
           actionButton("exclude_reset", "Reset")
    )
  )
)

server <- function(input, output) {
  # For storing which rows have been excluded
  vals <- reactiveValues(
    keeprows = rep(TRUE, nrow(XYdata))
  )
  NonScientific <- function(l) {l <- format(l, scientific = FALSE); parse(text=l)}

  output$plot1 <- renderPlot({
    # Plot the kept and excluded points as two separate data sets

    XYdata <- data.frame(cbind(Values = c(91.8, 95.3,   99.8,   123.3,  202.9,  619.8,  1214.2, 1519.1, 1509.2, 1523.3, 1595.2, 1625.1),
                           Concn = c(1000, 300,    100,    30, 10, 3,  1,  0.3,    0.1,    0.03,   0.01,   0)))
    keep    <- XYdata[ vals$keeprows, , drop = FALSE]
    exclude <- XYdata[!vals$keeprows, , drop = FALSE]
    keep <- subset(keep, Concn > 0)
    exclude <- subset(exclude, Concn > 0)
    o <- order(keep$Concn)
    keep <- keep[o, ]
    fo <- Values ~ (ymax* Concn / (ec50 + Concn)) + Ns * Concn + ymin
    st <- list(ymax=max(keep$Values), ymin = min(keep$Values), ec50 = 3, Ns = 0.2045514)
    nls.fit <- nls(fo, data = keep, start = st)
    plot(Values ~ Concn, keep, subset = Concn > 0, type = 'p',pch = 16,cex = 2, axes = FALSE, frame.plot = TRUE,log = "x")
    title(main = "Interactive Std curve")
    logRange <- with(keep, log(range(Concn[Concn > 0])))
    x <- exp(seq(logRange[1], logRange[2], length = 250))
    lines(x, predict(nls.fit, new = list(Concn = x)))
    points(Values ~ Concn, exclude, subset = Concn > 0, col = 1, cex = 2)
    my.at <- 10^(-2:3)
    axis(1, at = my.at, labels = formatC(my.at, format = "fg"))
    axis(2)
  })

  # Toggle points that are clicked
  observeEvent(input$plot1_click, {

    res <- nearPoints(XYdata, input$plot1_click, xvar="Concn", yvar="Values", allRows = TRUE)
    vals$keeprows <- xor(vals$keeprows, res$selected_)
  })

  # Reset all points
  observeEvent(input$exclude_reset, {
    vals$keeprows <- rep(TRUE, nrow(XYdata))
  })      
}

shinyApp(ui, server)

enter image description here

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.