这是我第一次使用 R 中的列表(到目前为止仅使用数据帧),我试图了解如何从响应式(Reactive)框架访问和更改列表中的不同元素/级别/名称。底部发布的 MWE 代码提供了一个操作按钮,可生成其他列表元素,并在 for 循环中按顺序对一级列表元素名称进行编号,并且在 R studio 控制台中在 Shiny 中运行此代码时,您可以看到列表的演变.
如下所示,我的问题是如何从代码中的 for 循环到 for 访问 reactiveValues
对象 uiTbl
的列表元素名称例如,将每个名称中的“div”更改为“hello”? (最终在完整的代码中,我将重新排序每个“div...”标签的编号,但我可以稍后再做,现在我只是想了解如何操作 react 列表)。我正在尝试从 observe()
中更改列表元素的名称。该代码对一级名称(“Col...”)执行此操作,但我无法弄清楚如何转到“div...”的更高列表级别名称。在下图中,黑色“解释”(哈哈)R Studio 控制台中的当前代码输出,红色显示我正在尝试执行的操作。
我对列表的理解非常有限,因此我上面的描述可能会很糟糕,我当然热切地接受错误的纠正。
代码:
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 值的名称。
替代选项
区分
- 内部键以编程方式识别对象
- 在 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/