r - 如何从观察者修改reactiveValues列表元素的名称?

标签 r list shiny reactive-programming shiny-reactivity

这是我第一次使用 R 中的列表(到目前为止仅使用数据帧),我试图了解如何从响应式(Reactive)框架访问和更改列表中的不同元素/级别/名称。底部发布的 MWE 代码提供了一个操作按钮,可生成其他列表元素,并在 for 循环中按顺序对一级列表元素名称进行编号,并且在 R studio 控制台中在 Shiny 中运行此代码时,您可以看到列表的演变.

如下所示,我的问题是如何从代码中的 for 循环到 for 访问 reactiveValues 对象 uiTbl 的列表元素名称例如,将每个名称中的“div”更改为“hello”? (最终在完整的代码中,我将重新排序每个“div...”标签的编号,但我可以稍后再做,现在我只是想了解如何操作 react 列表)。我正在尝试从 observe() 中更改列表元素的名称。该代码对一级名称(“Col...”)执行此操作,但我无法弄清楚如何转到“div...”的更高列表级别名称。在下图中,黑色“解释”(哈哈)R Studio 控制台中的当前代码输出,红色显示我正在尝试执行的操作。

我对列表的理解非常有限,因此我上面的描述可能会很糟糕,我当然热切地接受错误的纠正。

enter image description here

代码:

library(shiny)

data1 <- data.frame(row.names = c("A","B"),"Col 1"=c(1,2),check.names=FALSE)

ui <- fluidPage(hr(),actionButton("add","Add element"))

server <- function(input,output,session) {
  uiTbl <- reactiveValues(div_1_tbl = data1)
  
  observeEvent(input$add, {
    divID <- paste0("div_", input$add+1)
    uiTbl[[paste0(divID,"_tbl")]] <- data1 
  })
  
  observe({
    tables_list <- reactiveValuesToList(uiTbl)
    table_lengths <- lengths(tables_list)
    cumsum_table_lengths <- cumsum(table_lengths)[table_lengths != 0L]
    
    # below adds sequential numbering to the "Col" name for each list element
    for(i in seq_along(cumsum_table_lengths)){
      names(uiTbl[[names(cumsum_table_lengths[i])]]) <- paste("Col", cumsum_table_lengths[i])
      print(uiTbl[[names(cumsum_table_lengths[i])]]) # shows results of above in console
    }
    print(names(uiTbl)) # shows name tags of list elements (did I say this right?) in console
  })

}

shinyApp(ui, server)

最佳答案

看起来 Shiny 框架明确想要排除这个用例。许多观察都表明了这一假设。该实现做了很多工作,使得初始化后无法更改无功值的名称。不仅内部对象结构相当复杂(见下文)。访问ReactiveValues的方法对象将复杂性隐藏在非常简单的 API 背后。这个简单的 API 覆盖了更改元素名称的函数:有一个覆盖 S3 names<- 的实现。方法。函数shiny:::``names<-.reactivevalues`` 抛出错误而不做任何其他事情。

总而言之:即使有人找到了规避这些预防措施的方法,也不建议即时更改 react 值的名称。

替代选项

区分

  1. 内部键以编程方式识别对象
  2. 在 UI 中向用户显示的可显示标签

这种方法不仅在您的情况下是常见做法。通过这种方式,您可以获得识别对象的稳定 key ,但您可以向用户展示他们理解应用程序所需的任何标签。它还使您免受某些限制。内部有某些限制(请参阅 ?make.names ),用户不理解并且可能会感到困惑。

此方法需要第二个对象来映射内部键以显示标签。一个简单的结构 `(key = "displayname", ...) 就可以了。

对象结构

这里有一些更多的细节来解释为什么很难访问这些名字。 uiTbl是S3类的列表reactivevalues 。它包含三个元素,其中之一是 R6 ReactiveValues类(class)。并且该类不提供对您存储在 uiTbl 中的值的直接访问。但包含成员 .values这是另一个 R6 类 Map 。此类的数据是私有(private)的(即不能从外部访问)。没有允许您更改元素名称的函数。

uiTbl (list as S3 class `reactivevalues`)
├──impl (R6 class `ReactiveValues`)
│  ├── .values (R6 class `Map`)
│  |   ├── map: list (no access because private)
│  |   └── ... further public methods
│  └── ... further public and private members
├──readonly (TRUE/FALSE)
└──ns (name space)

关于r - 如何从观察者修改reactiveValues列表元素的名称?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74918479/

相关文章:

javascript - 如何在 Shiny 的仪表板侧栏中手动展开子菜单

r - R怎么知道我没有某种类型的条目

斯坦福解析器的 R 接口(interface)

r - 如何显示列表的元素

C# 是否清除具有值类型的 List<T> 仍然是 O(n) 操作?

r - 使用 if-else 从下拉列表中进行多项选择 R Shiny

r - 在 Axis 标签周围添加圆圈

c# - 获取列表中某一列上有不同的所有行

python - 在不同行中打印列表中的多个项目

css - 定位 R Shiny 的 selectInput 小部件