简体   繁体   English

R Shiny - 是否可以嵌套反应函数?

[英]R Shiny - Is it possible to nest reactive functions?

In R-Shiny.在 R-Shiny 中。 Trying to break up a really long reactive function (thousands of lines.), Hypothetically, is it possible to nest conditional reactive functions: something similar to:试图分解一个非常长的反应式 function (数千行。),假设,是否可以嵌套条件反应函数:类似于:

STATE_filter <- reactive({
 
   if(input$selectcounty ends with "-AL") {
    run AL_filter()
  }
  else if (input$selectstate ends with "-AR"){
    run AR_filter()
  }
  else {
    return("ERROR")
  }
})

EDIT编辑

Non-hypothetically, I'm trying to create a nested reactive filtering function based on user select inputs of US counties.非假设地,我正在尝试根据美国各县的用户 select 输入创建嵌套的无功滤波 function。 Upon their selection of county, a circlepackeR graph should pop up in a modal dialog box.在他们选择县后,一个 circlepackeR 图表在模式对话框中弹出。 This is the data I am using:这是我正在使用的数据:

dput(head(demographics))
structure(list(NAME = c("Autauga-AL", "Baldwin-AL", "Barbour-AL", 
"Bibb-AL", "Blount-AL", "Bullock-AL"), STATE_NAME = c("AL", "AL", 
"AL", "AL", "AL", "AL"), gender = structure(c(2L, 2L, 2L, 2L, 
2L, 2L), .Label = c("female", "male"), class = "factor"), hispanic = structure(c(2L, 
2L, 2L, 2L, 2L, 2L), .Label = c("hispanic", "nonhispanic"), class = "factor"), 
    race = structure(c(6L, 6L, 6L, 6L, 6L, 6L), .Label = c("asian", 
    "black", "islander", "native", "two or more", "white"), class = "factor"), 
    makeup = structure(c(2L, 2L, 2L, 2L, 2L, 2L), .Label = c("in combination", 
    "one race", "two or more"), class = "factor"), r_count = c(456L, 
    1741L, 114L, 96L, 320L, 44L), pathString = c("world/male/nonhispanic/white/one race", 
    "world/male/nonhispanic/white/one race", "world/male/nonhispanic/white/one race", 
    "world/male/nonhispanic/white/one race", "world/male/nonhispanic/white/one race", 
    "world/male/nonhispanic/white/one race")), row.names = c(NA, 
6L), class = "data.frame")

Here's an example of the reactive function I'm using below.这是我在下面使用的反应式 function 的示例。 It's a small subset of 10,000 + lines, and I want to "nest" it by splitting the lines by state (AL for Alabama, AR for Arkansas) first so it's a cleaner piece of code.它是 10,000 多行的一个小子集,我想首先通过 state(阿拉巴马州的 AL,阿肯色州的 AR)拆分行来“嵌套”它,所以它是一段更干净的代码。

demographics_filter <- reactive({
   if(input$selectcounty == "Autauga-AL") {
    race_autauga <- subset.data.frame(demographics, NAME=="Autauga-AL")
    nodes_autauga <- as.Node(race_autauga)
  } 
  else if(input$selectcounty== "Baldwin-AL") {
    race_baldwinAL <-subset.data.frame(demographics, NAME=="Baldwin-AL")
    nodes_baldwinAL<- as.Node(race_baldwinAL)
  } 
 else if(input$selectcounty== "Ashley-AR") {
    race_AshleyAR <-subset.data.frame(race, NAME=="Ashley-AR")
    nodes_AshleyAR<- as.Node(race_AshleyAR)
  }
  else {
    return("ERROR!")
  }
})

And finally, here's the graph in my server that's utilizing this function:最后,这是我的服务器中使用此 function 的图表:

     output$circle_graph_of_demographics <- renderCirclepackeR({
      circlepackeR(demographics_filter(), size = "r_count"
    })  

Speaking personally, if a single function/reactive is 1000s of lines long, there's definitely room for improvement through refactorisation!就个人而言,如果单个函数/响应式是 1000 行长,那么通过重构肯定有改进的空间!

One thing I find strange about the demographics_filter reactive you've given us is that it returns NULL in the case of valid data and "ERROR!"我对你给我们的demographics_filter过滤器反应感到奇怪的一件事是,它在有效数据和"ERROR!"的情况下返回NULL in the case of invalid data, so I'm not sure how you can use it successfully in output$circle_graph_of_demographics .在数据无效的情况下,所以我不确定如何在output$circle_graph_of_demographics中成功使用它。 If you don't need it to return anything, then perhaps an eventReactive(input$selectcounty, {...}) would be more appropriate?如果您不需要它返回任何内容,那么eventReactive(input$selectcounty, {...})可能更合适?

It looks as if you need to create both a (set of) nodes and a (set of) filtered data frames based on changes to the value of input$selectcounty .看起来好像您需要根据input$selectcounty的值的更改来创建(一组)节点和(一组)过滤数据帧。 It's not clear why you need a node and subset for, say, Autauga-Al when input$selectcounty is, say, Baldwin-AR , which is why I've put "set of" in brackets.目前尚不清楚为什么当input$selectcountyBaldwin-AR时,为什么需要Autauga-Al的节点和子集,这就是我将“set of”放在括号中的原因。

Based on what you've told us (without a MWE, it's impossible to be sure exactly what will suit your needs), I would do something like:根据您告诉我们的内容(没有 MWE,无法确定到底什么适合您的需求),我会做类似的事情:

demographics_filter <- reactive({
  req(input$selectcounty)
  subset.data.frame(demographics, NAME==input$selectcounty)
})

demographics_node <- reactive({
  as.Node(demographics_filter())
})

which should provide a compact solution that is robust with respect to changes in county and state names.这应该提供一个紧凑的解决方案,该解决方案对于县和 state 名称的变化是稳健的。 If I understand you correctly, this replaces your many-thousands-of-lines with just seven.如果我理解正确的话,这会用七行替换你的数千行。 Obviously, you may need to refactor the rest of your code to take account of your changes.显然,您可能需要重构代码的 rest 以考虑您的更改。

If you do need sets of filtered data frames and nodes, then I'd do something like this:如果您确实需要过滤数据帧和节点集,那么我会做这样的事情:

v <- reactiveValues(
       demographics_filter=list(),
       demographics_nodes=list()
     )

eventReactive(input$selectcounty, {
  req(input$selectcounty)
  v$demographics_filter[[input$selectcounty]] <- subset.data.frame(demographics, NAME==input$selectcounty)
  v$demographics_node[[input$selectcounty]] <- as.Node(v$demographics_filter[[input$selectcounty]])
})

Again, it's a compact, robust solution, and you may need to refactor your code elsewhere to take account of the changes.同样,它是一个紧凑、健壮的解决方案,您可能需要在别处重构代码以考虑更改。

All my code is untested because I don't have a MWE to work with.我所有的代码都未经测试,因为我没有MWE可以使用。

Got it!知道了!

yes, you (I) can nest reactive functions.是的,你(我)可以嵌套反应函数。

### ALABAMA FILTER
al_filter <- reactive({
  if(input$selectcounty == "Autauga-AL") {
    demographics_autauga <- subset.data.frame(demographics, NAME=="Autauga-AL")
    nodes_autauga <- as.Node(demographics_autauga)
  } 
  else {
    return("ERROR2")
  }
})

##### ARKANSAS FILTER
ar_filter <- reactive ({
  if(input$selectcounty== "Arkansas-AR") {
    demographics_ArkansasAR <-subset.data.frame(demographics, NAME=="Arkansas-AR")
    nodes_ArkansasAR<- as.Node(demographics_ArkansasAR)
  }   
  else {
    return("ERROR2")
  }
})

##### STATES FILTER
demographics_filter <- reactive({
   if(grepl("-AL", input$selectcounty)){
    return(al_filter())
  }
  else if (grepl("-AR", input$selectcounty)){
    return (ar_filter())
  }
  else {
    return(" ERROR")
  }
})

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

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