如何用purrr::map替代lapply实现Shiny绘图输出赋值?
用purrr::map替代lapply实现Shiny多图表渲染的问题解决
原正常运行代码
你原本用lapply可以正常生成多个Shiny图表:
library(shiny) library(tidyverse) mylist <- c(1,2,3) %>% as.list() ui <- fluidPage( plotOutput('chart_1'), plotOutput('chart_2'), plotOutput('chart_3') ) server <- function(input, output, session) { lapply(1:3, function(x){ output[[paste0("chart_", x)]] <- renderPlot({ ggplot(gapminder::gapminder %>% filter(country == 'Chile'), aes(x = year, y = pop))+ geom_line()}) }) } shinyApp(ui, server)
你尝试的错误代码
想用purrr::map替代但报错:
mylist %>% map(~ output[[glue::glue("chart_{.x}")]] <- renderPlot({ ggplot(gapminder::gapminder %>% filter(country == 'Chile'), aes(x = year, y = pop))+ geom_line()}) )
问题原因与解决方法
核心问题
map的定位是转换数据并返回结果,而给output对象赋值属于「副作用操作」(只修改外部对象,不产生需要返回的结果),这类场景更适合用purrr::walk。- 用
~简写函数时,多语句操作需要用{}包裹,否则语法解析会出错。
正确代码
把map换成walk,并给映射内容加上{}:
server <- function(input, output, session) { mylist %>% walk(~ { output[[glue::glue("chart_{.x}")]] <- renderPlot({ ggplot(gapminder::gapminder %>% filter(country == 'Chile'), aes(x = year, y = pop)) + geom_line() }) }) }
如果不想用glue,也可以和原代码保持一致用paste0:
server <- function(input, output, session) { mylist %>% walk(~ { output[[paste0("chart_", .x)]] <- renderPlot({ ggplot(gapminder::gapminder %>% filter(country == 'Chile'), aes(x = year, y = pop)) + geom_line() }) }) }
内容的提问来源于stack exchange,提问作者Cassio DS
相关产品推荐
相关产品推荐

