简体   繁体   English

select 基于复选框选择并显示热图的 Rshiny 中 data.frame 的多列

[英]select multiple columns from data.frame in Rshiny based upon checkbox selection and display heatmap

Good day all,大家好,

I am new to Rshiny and been playing around with user reactive elements.我是 Rshiny 的新手,一直在玩用户反应元素。 I am trying to create a heatmap that essentially takes a data.frame as input - where the user can select the number of rows and columns to be displayed.我正在尝试创建一个基本上以 data.frame 作为输入的热图 - 用户可以在其中 select 要显示的行数和列数。 Particularly if a user select a checkbox option, a number of columns would be selected (or deselected if checkbox is not selected).特别是如果用户 select 有一个复选框选项,则会选择一些列(如果未选中复选框,则取消选择)。

My example code looks like this - it takes a TSV input file of 99 elements (for rows), and has 20 columns of values.我的示例代码如下所示 - 它采用 99 个元素(用于行)的 TSV 输入文件,并具有 20 列值。 I give the option to increase decrease rows as a slider, and 5 checkboxes - denoting "col_group_xx", such that each checkbox selects a group of 4 columns - adding or removing those columns from the heatmap.我提供了增加减少行的选项,如 slider 和 5 个复选框 - 表示“col_group_xx”,这样每个复选框选择一组 4 列 - 从热图中添加或删除这些列。 ie "col_group_1" would select or deselect the first 4 columns, "col_group_2" for columns 5 to 8, and so on.即“col_group_1”将 select 或取消选择前 4 列,“col_group_2”用于第 5 到 8 列,依此类推。

My row slider works and the heatmap appropriately reduces or increases rows, but I can't seem to figure out how to connect the checkboxes to select each group of columns -我的行 slider 有效,热图适当地减少或增加行,但我似乎无法弄清楚如何将复选框连接到 select 每组列 -

It returns this error -它返回此错误 -

Warning: Error in [.data.frame: undefined columns selected
  [No stack trace available]

download sample TSV input file here - https://github.com/sid5427/downloader/raw/master/example_matrix_for_heatmap.txt在此处下载示例 TSV 输入文件 - https://github.com/sid5427/downloader/raw/master/example_matrix_for_heatmap.txt

github link to code for easy download - https://github.com/sid5427/downloader/raw/master/cleaned_variable_heatmap_eg.R github 代码链接以便于下载 - https://github.com/sid5427/downloader/raw/master/cleaned_variable_heatmap_eg.ZE1E1D3D40573127E36EE0480CAF1

my code is as follows -我的代码如下 -

library(d3heatmap)
library(RColorBrewer)
library(shiny)
library(shinythemes)
library(reprex)
library(dplyr)


data<-read.csv("example_matrix_for_heatmap.txt", header=TRUE, row.names = 1, sep="\t")
rownames(data)
nrow(data)
dim(data)

new_data_matrix <- data.frame(rownames(data))

colnames <- c("col_group_1","col_group_2","col_group_3","col_group_4","col_group_5")

####ui####
ui<-fluidPage(
  titlePanel("example_heatmap"), 
  theme=shinytheme("cerulean"),

  sidebarPanel(
    sliderInput("obs",
                "Number of observations:",
                min = 1,
                max = nrow(data),
                value = nrow(data)),
    tableOutput("values"),

    #group of checkboxes
    checkboxGroupInput("checkGroup", 
                       label = h3("columns to select"),
                       choices = colnames,
                       selected = colnames)
  ),

  mainPanel(
    d3heatmapOutput("heatmap", 
                    height="1200px", width="80%")
  ),


  fluidRow(column(3, verbatimTextOutput("value")))
)

####server####
server <- function(input, output) 
{
  output$value <- renderPrint({ input$checkGroup })

  observeEvent(input$checkGroup,{
    if("col_group_1" %in% input$checkGroup){
      print("col_group_1") ##debuging
      new_data_matrix <- cbind(new_data_matrix,data[,1:4])
    }
    if("col_group_2" %in% input$checkGroup ){
      print("col_group_2") ##debuging
      new_data_matrix <- cbind(new_data_matrix,data[,5:8])
    }
    if("col_group_3" %in% input$checkGroup ){
      print("col_group_3") ##debuging
      new_data_matrix <- cbind(new_data_matrix,data[,9:12])
    }
    if("col_group_4" %in% input$checkGroup ){
      print("col_group_4") ##debuging
      new_data_matrix <- cbind(new_data_matrix,data[,13:16])
    }
    if("col_group_5" %in% input$checkGroup ){
      print("col_group_5") ##debuging
      new_data_matrix <- cbind(new_data_matrix,data[,17:20])
    }
    dim(new_data_matrix) ##debuging
  })

  output$heatmap <- renderD3heatmap({
    d3heatmap(new_data_matrix[1:input$obs,2:ncol(new_data_matrix)],
              col=brewer.pal(9,"Reds"),
              scale="none")}
  )
}

shinyApp(ui, server)

Any help would be appreciated!任何帮助,将不胜感激! Plus if there is a more efficient way of doing this via dplyr I would appreciate that as well!另外,如果有更有效的方法通过 dplyr 执行此操作,我也将不胜感激!

Agree with @r2evans suggestion, you can use a reactive block.同意@r2evans 的建议,您可以使用reactive块。 You can set up two blocks (one to select columns, and one to subset your data based on these selected columns).您可以设置两个块(一个用于 select 列,一个用于根据这些选定的列对数据进行子集化)。

In the example below I just use one reactive block to subset based on both observations and columns.在下面的示例中,我只使用一个reactive块来根据观察和列进行子集化。 In addition, it might be easier to have a simple table that relates groups to specific ranges of columns (in this case col_group ).此外,拥有一个将组与特定范围的列(在本例中col_group )相关联的简单表可能更容易。 This could be modified for your needs and may allow for some flexibility.这可以根据您的需要进行修改,并且可能具有一定的灵活性。

The reactive block will determine which column ranges to use. reactive块将确定要使用的列范围。 With the Map function you can put all the fields together in a single vector to use in subsetting data.使用Map function,您可以将所有字段放在一个向量中以用于子集数据。

Also added validate in renderD3heatmap , which would make sure you have at least one group checked, and that you have at least 2 observations based on your input slider.还在renderD3heatmap中添加了validate ,这将确保您至少检查了一组,并且根据您的输入 slider,您至少有 2 个观察值。

library(d3heatmap)
library(RColorBrewer)
library(shiny)
library(shinythemes)
library(reprex)
library(dplyr)

data<-read.csv("example_matrix_for_heatmap.txt", header=TRUE, row.names = 1, sep="\t")

col_group <- data.frame(
  group = c("col_group_1","col_group_2","col_group_3","col_group_4","col_group_5"),
  min_col = c(1, 5, 9, 13, 17),
  max_col = c(4, 8, 12, 16, 20)
)

####ui####
ui<-fluidPage(
  titlePanel("example_heatmap"), 
  theme=shinytheme("cerulean"),

  sidebarPanel(
    sliderInput("obs",
                "Number of observations:",
                min = 1,
                max = nrow(data),
                value = nrow(data)),
    tableOutput("values"),

    #group of checkboxes
    checkboxGroupInput("checkGroup", 
                       label = h3("columns to select"),
                       choices = col_group[, "group"],
                       selected = col_group[, "group"])
  ),

  mainPanel(
    d3heatmapOutput("heatmap", 
                    height="1200px", width="80%")
  ),


  fluidRow(column(3, verbatimTextOutput("value")))
)

####server####
server <- function(input, output) 
{
  new_data_matrix <- reactive({
    col_ranges <- col_group %>% 
      filter(group %in% input$checkGroup)

    all_cols <- unlist(Map(`:`, col_ranges$min_col, col_ranges$max_col))

    data[1:input$obs, all_cols]
  })

  output$heatmap <- renderD3heatmap({
    validate(
      need(input$checkGroup, 'Check at least one group!'),
      need(input$obs >= 2, 'Need at least 2 groups to cluster!')
    )
    d3heatmap(new_data_matrix(),
              col=brewer.pal(9,"Reds"),
              scale="none")
  })
}

shinyApp(ui, server)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM