使用和不使用 ggplot 的交互式 R Shiny 绘图

Posted

技术标签:

【中文标题】使用和不使用 ggplot 的交互式 R Shiny 绘图【英文标题】:Interactive R Shiny plot with and without using ggplot 【发布时间】:2017-08-22 04:37:41 【问题描述】:

我修改了 R Shiny 库中的交互式 R Shiny 图以绘制交互式标准曲线。我想在不使用 ggplot2 库的情况下仅使用 R 基础绘图函数来绘制交互式绘图。

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)

我尝试用以下内容替换脚本的绘图部分,但我无法交互式绘图。我在这里做错了什么?

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

【问题讨论】:

【参考方案1】:

您必须将xvaryvar参数添加到nearPoints

res <- nearPoints(XYdata, input$plot1_click, xvar="Concn", yvar="Values", allRows = TRUE)

【讨论】:

嗨@HubertL,你的建议奏效了。我现在面临的唯一问题是我无法用更详细的标题覆盖轴标题。你能看看下面的代码吗?无论我做什么,它都会覆盖“Concn”和“Values”,造成混乱。请问有什么建议吗? 只需将这些参数添加到绘图调用ylab="", xlab=""【参考方案2】:

实现@HubertL 对像我这样的人的建议的工作代码用于交互式绘图并通过单击或使用鼠标选择点来剔除异常值:

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)

【讨论】:

以上是关于使用和不使用 ggplot 的交互式 R Shiny 绘图的主要内容,如果未能解决你的问题,请参考以下文章

R Shiny:交互式输入从 rds 文件进入 ggplot 时出错(评估中的错误:找不到对象'x')

数据故事使用R进行交互式数据可视化

使用 ggplotly rangeslider 进行交互式相对性能(股票收益)

在 R 中用 Shiny 绘制散点图;情节没有更新,也没有完全互动

数据可视化应用用Python通过ggplot2实现交互可视化(附Python应用案例)

R和Shiny:当悬停在Shiny上的绘图上时显示ggplot2数据值