【发布时间】:2021-03-29 05:27:14
【问题描述】:
我有下面的代码,它允许用户上传 Excel,重命名列,然后围绕热门术语进行一些快速分析等(第一列必须命名为“评论”)。
发生的情况是,当我上传文件 > 重命名我的第一列 > 然后单击快速分析时,它会运行代码 4 次,因此它会不断刷新。我删除了那里的其他 3 张桌子以使其更容易。我想我需要在某个地方使用isolate(),但我不确定。
# Toy Example.
library(needs)
needs(
shiny,
ggplot2,
tidyverse,
shinydashboard,
DT,
shinycssloaders,
plotly,
shinyjs,
dashboardthemes,
reactable,
quanteda
)
## app.R ##
library(shiny)
library(shinydashboard)
convertMenuItem <- function(mi, tabName) {
mi$children[[1]]$attribs['data-toggle'] = "tab"
mi$children[[1]]$attribs['data-value'] = tabName
mi
}
header = dashboardHeader()
sidebar = dashboardSidebar(
width = 300,
sidebarMenu(
id = 'panelsbar',
convertMenuItem(tabName = 'home', menuItem(
'Home', tabName = 'home', icon = icon('home')
)),
convertMenuItem(
tabName = 'data',
menuItem(
'Data Input',
tabName = 'data',
fileInput(
"file",
"Upload CSV files",
multiple = TRUE,
accept = ("text/comma")
),
uiOutput('textColumn'),
actionButton('go', 'Run')
)
),
convertMenuItem(
tabName = 'variables',
menuItem('Variable Renaming', tabName = 'variable',
uiOutput("renamer"))
),
convertMenuItem(tabName = 'quickAnalysis',
menuItem('Quick Analysis',
tabName = 'quickAnalysis'))
)
)
body <- dashboardBody(
shinyDashboardThemes('grey_light'),
tabItems(
tabItem(tabName = 'home'),
tabItem(tabName = 'data',
fluidRow(
box(
width = 12,
title = 'Data Input',
solidHeader = T,
status = 'primary',
collapsible = T,
reactableOutput('rawData')
)
)),
tabItem(tabName = 'variable',
dataTableOutput("rename")),
tabItem(tabName = 'quickAnalysis',
fluidRow(
box(
width = 6,
title = 'Top Terms',
solidHeader = T,
plotlyOutput('topTerms')
),
box(
width = 6,
title = 'Top bigrams',
solidHeader = T,
dataTableOutput('topBis')
)
),
fluidRow(
box(
width = 6,
title = 'Top 75 Terms',
solidHeader = T,
plotOutput('wordcloudTopTerms') %>%
withSpinner()
),
box(width = 6, dataTableOutput('x1'))
))
)
)
ui = shinydashboard::dashboardPage(header, sidebar, body,
tags$head(tags$style(
HTML(".sidebar {
height: 90vh; overflow-y: auto;
}")
)))
server = server <- function(input, output) {
options(shiny.maxRequestSize = 30 * 1024 ^ 2)
dataa <- reactive({
req(input$file)
read.csv(input$file$datapath)
})
output$contents <- renderDataTable({
dataa()
})
output$rawData = renderReactable({
reactable(
dataa(),
filterable = T,
resizable = T,
showPagination = T,
showSortIcon = T,
defaultPageSize = 10
)
})
# rename variables --------------------------------------------------------
output$renamer <- renderUI({
lapply(colnames(dataa()), function(i) {
textInput(paste0("col_", i), i, i)
})
})
DataRename <- reactive({
req(input$file)
Data <- dataa()
DataNew1 <- Data
for (i in names(input)) {
if (grepl(pattern = "col_", i)) {
colnames(DataNew1)[which(colnames(DataNew1) == substr(i, 5, nchar(i)))] =
input[[i]]
}
}
return(DataNew1)
})
output$rename <- renderDataTable({
DataRename()
})
numComments = reactive({
sum(!is.na(df$Comments))
})
# Text analysis -----------------------------------------------------------
x = do.call(c,
unlist(stopwords::data_stopwords_marimo$en, recursive = F))
x = c(stopwords(), x, 'takeda')
x = c(x, stopwords::data_stopwords_stopwordsiso$en)
stop_words = unique(x)
corp = reactive({
req(DataRename())
x = corpus(DataRename(), text_field = 'Comments')
})
dm = reactive({
df = DataRename()
corp = corp()
x = corp %>%
dfm(
tolower = T,
remove = stop_words,
remove_punct = T,
remove_symbols = T,
remove_numbers = T
)
})
topTerms = reactive({
dm = dm()
x = dm() %>%
textstat_frequency()
})
getTopTerms = reactive({
x = topTerms()
x %>% as.data.frame() %>%
mutate(Frequency = round((docfreq / numComments()) * 100, 1)) %>%
select(-c(group, frequency, rank)) %>%
rename(Count = docfreq,
Terms = feature)
})
plotTerms = reactive({
top = getTopTerms()
top = top %>% arrange(desc(Frequency)) %>% top_n(15)
p = plot_ly(
data = top,
type = 'bar',
y = ~ Terms,
x = ~ Frequency,
source = 'topterms'
)
p
})
output$topTerms = renderPlotly({
plotTerms()
})
}
shinyApp(ui, server)
【问题讨论】:
-
DataRename 对
input有反应性依赖(通过for (i in names(input)) {行,您是否尝试隔离它?当any 时刷新依赖于input的反应性输入变化。 -
啊,好吧,就像
isolate( for (i in names(input)) { if (grepl(pattern = "col_", i)) { colnames(DataNew1)[which(colnames(DataNew1) == substr(i, 5, nchar(i)))] = input[[i]] ) -
Ted,我不这么认为,因为从技术上讲,您确实想对文本字段做出反应,不是吗?如果您只想在按下“开始”按钮时做出反应,那么可以,您也可以隔离
input[[i]]。我不认为isolate这样的大表达式一般来说不是一个好主意,尽管我不知道除了电锯修复之外的任何技术障碍或限制。