在R中创建交互式图表

3
使用plotly库,我在R中制作了以下图表:
library(dplyr)
library(ggplot2)
library(plotly)

set.seed(123)
df <- data.frame(var1 = rnorm(1000,10,10),
                   var2 = rnorm(1000,5,5))

df <- df %>% mutate(var3 = ifelse(var1 <= 5 & var2 <= 5, "a", ifelse(var1 <= 10 & var2 <= 10, "b", "c"))) 


plot = df %>%
  ggplot() + geom_point(aes(x=var1, y= var2, color= var3))


ggplotly(plot)

enter image description here

这是一个简单的散点图 - 生成两个随机变量,然后通过某些标准来决定点的颜色(例如,如果var1和var2在一定范围内)。
从这里,我还可以得出汇总统计信息:
df$var3 = as.factor(df$var3)
summary = df %>%
    group_by(var3) %>%
    summarize(Mean_var1 = mean(var1), Mean_var2 = mean(var2), count=n())

# A tibble: 3 x 4
  var3  Mean_var1 Mean_var2 count
* <fct>     <dbl>     <dbl> <int>
1 a         -1.70     0.946   158
2 b          4.68     4.94    260
3 c         15.8      6.49    582

我的问题是:是否可以向这个绘图添加一些按钮,使用户可以根据自定义选择对点进行着色?例如,像这样:

enter image description here

现在,用户可以输入任何他们想要的范围 - 点的颜色会改变,并生成一些摘要统计信息。
有人能向我展示如何在R中实现这个功能吗?
我有一个想法 - 首先我会创建一个巨大的表格,它将创建所有可能的"var1"和"var2"范围组合:
vec1 <- c(-20:40,1)
vec2 <-  c(-20:40,1)


a <- expand.grid(vec1, vec2)

for (i in seq_along(vec1)) { 
    for (j in seq_along(vec2)) {

df <- df %>% mutate(var3 = ifelse(var1 <= i & var2 <= i, "a", ifelse(var1 <= j & j <= 10, "b", "c"))) 

}

}

接着,根据用户想要的范围 - 一个类似SQL语句的语句将来自这个巨大表格的行隔离出来,对应于那些范围:

custom_df = df[df$var1 > -20 & df$var1 <10 & df$var1 > -20 & df$var2 <10 , ]    

然后,将为“custom_df”创建一个个体图,并记录“custom_df”的摘要统计信息:
summary = custom_df %>%
    group_by(var3) %>%
    summarize(Mean_var1 = mean(var1), Mean_var2 = mean(var2), count=n())

但我不确定如何在R中整洁高效地完成这个任务。

enter image description here

有人可以向我展示如何做到这一点吗?

谢谢


1
你正在寻找 shiny 的解决方案吗? - akrun
1
这可能需要一些努力,这也可能是目前还没有答案的原因。如果你没有得到答案,另一个选择是提供一点悬赏以吸引更多人来关注它。 - akrun
1
这些链接非常有用。如果你自学,它会对你回答那些问题有很大帮助。 - akrun
1
谢谢,现在可能会得到更多关注。 - akrun
谢谢 - 我希望它也能做得很好。 - stats_noob
显示剩余5条评论
1个回答

10
我已经开发了一个小型的闪亮应用程序,以执行您大部分要求。基于预定义的大数据框 df,用户可以定义以下内容:
  1. 选择变量 var1var2 的最小值和最大值。
  2. 选择定义变量 var3 的标准,这用于显示不同颜色的数据点。现在是一个范围。
  3. 将绘图保存为HTML文件。
  4. 摘要统计信息以表格形式显示。
您可以定义更多选项,以便向用户提供选择颜色等选项。为此,您可以搜索如何使用 scale_color_manual()
更新:添加了用户选项,根据 var1 和 var2 范围值选择红色和绿色颜色。
library(shiny)
library(plotly)
library(dplyr)
library(DT)

### define a large df
set.seed(123)
df <- data.frame(var1 = rnorm(1000,10,10),
                 var2 = rnorm(1000,15,15))

ui <- fluidPage(
  titlePanel(p("My First Test App", style = "color:red")),
  sidebarLayout(
    sidebarPanel(
      p("Choose Variable limits"),

      # Horizontal line ----
      tags$hr(),
      uiOutput("var1a"), uiOutput("var1b"),
      uiOutput("var2a"), uiOutput("var2b"),
      uiOutput("criteria")

    ),
    mainPanel(
      DTOutput("summary"), br(),
      plotlyOutput("plot"),
      br(), br(), br(),
      uiOutput("saveplotbtn")
    )
  )
)

server <- function(input, output, session){
  
  output$var1a <- renderUI({
    tagList(
      numericInput("var11", "Variable 1 min",
                  min = min(df$var1), max = max(df$var1), value = min(df$var1))
    )
  })
  output$var1b <- renderUI({
    if (is.null(input$var11)){
      low1 <- min(df$var1)
    }else low1 <- max(min(df$var1),input$var11)  ## cannot be lower than var 1 minimum
    tagList(
      numericInput("var12", "Variable 1 max", min = low1, max = max(df$var1), value = max(df$var1))
    )
  })
  
  output$var2a <- renderUI({
    tagList(
      numericInput("var21", "Variable 2 min",
                   min = min(df$var2), max = max(df$var2), value = min(df$var2))
    )
  })
  output$var2b <- renderUI({
    if (is.null(input$var21)){
      low2 <- min(df$var2)
    }else low2 <- max(min(df$var2),input$var21)  ## cannot be lower than var 2 minimum
    tagList(
      numericInput("var22", "Variable 2 max", min = low2, max = max(df$var2), value = max(df$var2))
    )
  })
  
  output$criteria <- renderUI({
    req(input$var11,input$var12,input$var21,input$var22)
        
    tagList(
      sliderInput("crit11", "Variable 1 red color range:",
                  min = -10, max = 0, value = c(-10,0)),
      sliderInput("crit12", "Variable 2 red color range:",
                  min = -25, max = 0, value = c(-25,0)),
      sliderInput("crit21", "Variable 1 green color range:",
                  min = 0.1, max = 10, value = c(0.1,10)),
      sliderInput("crit22", "Variable 2 green color range:",
                  min = 0.1, max = 20, value = c(0.1,20))
    )

  })
  
  dat <- reactive({
    req(input$crit11,input$crit12,input$crit21,input$crit22)
    
    df <- df %>% filter(between(var1, input$var11, input$var12)) %>% 
                 filter(between(var2, input$var21, input$var22))
    
    # df1 <- df %>% mutate(var3 = ifelse(var1 <= i & var2 <= i, "a", ifelse(var1 <= j & var2 <= j , "b", "c")))
    
    df1 <- df %>% mutate(var3 = ifelse(between(var1, input$crit11[1], input$crit11[2]) & between(var2, input$crit12[1], input$crit12[2]), "a",
                                       ifelse(between(var1, input$crit21[1], input$crit21[2]) & between(var2, input$crit22[1], input$crit22[2]), "b", "c")))
    
  })
  
  summari <- reactive({
    req(dat())
    df1 <- dat()
    df1$var3 = as.factor(df1$var3)
    summary = df1 %>%
      group_by(var3) %>%
      dplyr::summarize(Mean_var1 = mean(var1), Mean_var2 = mean(var2), count=n())
  })
  
  output$summary <- renderDT(summari())
  
  rv <- reactiveValues()
  
  observe({
    req(dat())
    p <- ggplot(data=dat()) + geom_point(aes(x=var1, y= var2, color= var3))
    pp <- ggplotly(p)
    rv$plot <- pp
  })
  
  output$plot <- renderPlotly({
    rv$plot
  })
  
  output$saveplotbtn <-  renderUI({
    div(style="display: block; padding: 5px 350px 5px 50px;",
        downloadBttn("saveHTML",
                     HTML("HTML"),
                     style = "fill",
                     color = "default",
                     size = "lg",
                     block = TRUE,
                     no_outline = TRUE
        ) )
  })
  
  output$saveHTML <- downloadHandler(
    filename = function() {
      paste("myplot", Sys.Date(), ".html", sep = "")
    },
    content = function(file) {
      htmlwidgets::saveWidget(as_widget(rv$plot), file, selfcontained = TRUE)  ## self-contained
    }
  )

}

shinyApp(ui, server)

output


非常感谢您的回答!我正在考虑用“变量3范围”替换“标准1”和“标准2”。是否可能再添加一个框,记录每个范围组合的摘要统计信息?我无法感谢您的帮助! - stats_noob
如果答案符合您的要求,请通过点击复选标记接受它。如果您还没有这样做,您也应该考虑为此解决方案投票支持。 - iamericfletcher
@iamericfletcher:我已经点赞了这个解决方案。有几件事情我正在尝试从这个解决方案中修复(我在评论中提到了它们)。谢谢! - stats_noob
1
@stats555,接受已回答你的原始问题的答案被认为是礼貌的行为。这有助于那些正在寻找相同/类似查询解决方案的人们。此外,人们可能会愿意在你未来的查询中帮助你。 - YBS
抱歉 - 我现在已经接受了。我以为我已经点击了“接受”。我的道歉。 - stats_noob
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接