【发布时间】:2015-02-16 18:39:01
【问题描述】:
原问题贴在这里: Shiny reactive Unexpected Behavior
该问题正在此处重新发布,以尝试改进之前在上面提供的链接中发布的原始问题,因为我无法获得任何帮助。
目标:简而言之,此应用程序的目的是允许用户根据提供的各种输入对数据帧中提供的数据进行搜索、过滤、切片和切块给用户。
作为server 函数的一部分,定义了一个名为index 的反应函数来查找与用户输入对应的索引。反应函数index 使用grep 和which 函数来定位数据帧df 中的相应索引。
我已经包含了一个可重现的代码,并尝试在适当的情况下包含 cmets。
关于代码的进一步解释:
这个问题的标题只是我自己的猜测,它基于index中的代码是正确的假设。 index 中的代码可能存在根本问题,而 index 函数的反应性不一定。为了测试这一点,作为server 函数的一部分,我包含了一个函数printIndex 以打印index 的结果以确保它正常工作。
我亲自尝试将ind.j、ind.c、ind.l、ind.d、ind.s 和ind.all 的结果分别打印到控制台,它们似乎都产生了正确的结果.但是,当我测试ind 的结果时,它并不完全符合我的预期,所以我想知道是反应性还是代码行有问题。 ind 打算做的是获取存储在ind.all 中的所有查找索引的列表,并递归应用intersect 函数以从ind.all 中的所有子列表中查找公共元素。
如上所述,index 函数适用于单个过滤器。但是,当我为所有索引输入值时,作为用户,该函数不会按预期更新为正确的索引列表。例如,您可以尝试在Job textInput 中输入“application”,在Company selectizeInput 中输入“Gas Drive Global”,在Location textInput 同时点击Search!。您会看到数据表没有返回任何结果,而这显然对应于数据框df 的第一行。
#Load required packages
ListofPackages= c('shiny','ggplot2','scales')
lapply(ListofPackages,require,character.only=TRUE)
#Define the dataframe on which the search will be performed
df <- data.frame(Job=c('Applications Engineer ââ¬â Gas Drive',
'Engineer, Operations',
'Project Engineer',
'Project Engineer (Oil & Gas)',
'Project Engineer',
'Junior Engineer',
'Engineer, Operations',
'Research and Development (R&D) Junior Engineer',
'JUNIOR QUALITY ENGINEER',
'Junior Systems Design and Support Engineer',
'Mechanical Engineer Calgary, AB',
'Applications Engineer',
'Project Engineer',
'Pipeline Engineer',
'Development Engineer',
'Specialist Engineering Finance',
'Mechanical Engineer - Sudbury',
'Project Cost Analyst (12 month term)',
'Project Controls Functional Analyst',
'Project Controls Professionals'),
Company=c('Gas Drive Global',
'Agrium Wholesale',
'City of Calgary',
'Stantec',
'Shell',
'Canadian National Railway',
'Pembina Pipeline Corporation',
'Velan Inc.',
'G.W. Goudreau Personnel Services Ltd',
'Stratified Automotive Controls',
'Pason Systems Corp.',
'Howden',
'Plains Midstream Canada',
'Amec Foster Wheeler',
'Red Bend Software',
'Canadian Pacific',
'GENIVAR',
'Thales',
'AltaGas Ltd.','BEMAC Construction Corp.'),
Location=c('Calgary',
'Redwater',
'Calgary',
'Edmonton',
'Sarnia',
'Montréal',
'Calgary',
'Montréal',
'Windsor',
'Vancouver',
'Calgary',
'Winnipeg',
'Calgary',
'Calgary',
'Engineer',
'Calgary',
'Greater Sudbury',
'Ottawa',
'Calgary',
'Calgary'),
Posted=c(1,
1,
1,
2,
2,
1,
4,
5,
6,
4,
1,
5,
5,
3,
1,
1,
15,
1,
1,
13),
Source=c('Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed',
'Indeed'),
url=c('http://ca.indeed.com/rc/clk?jk=2371e16aab902f84',
'http://ca.indeed.com/rc/clk?jk=428facb738edd397',
'http://ca.indeed.com/rc/clk?jk=e15d8fe4d362279b',
'http://ca.indeed.com/rc/clk?jk=28c1464fd4e28b24',
'http://ca.indeed.com/rc/clk?jk=736ec57bf6902b93',
'http://ca.indeed.com/rc/clk?jk=bdc9999eae922645',
'http://ca.indeed.com/rc/clk?jk=3a4588fca0e600b1',
'http://ca.indeed.com/rc/clk?jk=71f1abcd100850c6',
'http://ca.indeed.com/cmp/G.W.Goudreau-Personnel-Services-Ltd/jobs/Junior-Quality-Engineer-3237601a1f3d3abc?r=1',
'http://ca.indeed.com/cmp/Stratified-Automotive-Controls/jobs/Junior-System-Design-Support-Engineer-1d916a435e69b8ce?r=1',
'http://ca.indeed.com/rc/clk?jk=fca9a784a37ece8a',
'http://ca.indeed.com/rc/clk?jk=b2d0975c638c03a8',
'http://ca.indeed.com/rc/clk?jk=c92725272c5f9ced',
'http://ca.indeed.com/rc/clk?jk=cd97c050df64787c',
'http://ca.indeed.com/rc/clk?jk=e6e278ed52532f73',
'http://ca.indeed.com/rc/clk?jk=a1f14d52c7798d7b',
'http://ca.indeed.com/rc/clk?jk=112350d5e020241f',
'http://ca.indeed.com/rc/clk?jk=a324c2dcade7dc5c',
'http://ca.indeed.com/rc/clk?jk=77895efdf28ad6fa',
'http://ca.indeed.com/cmp/BEMAC-Construction-Corp./jobs/Project-Control-Professional-90796e764f064a51?r=1'))
server <- function(input,output,session){
#Server-side search for the choices argument of selectizeInput in ui.R
updateSelectizeInput(session, 'c', choices = as.character(df$Company), server = TRUE)
#Create a reactive function to look up the indices correponding to the user's inputs
index <- reactive({
ind.j <- if(input$j=='') NULL else grep(input$j,df[,'Job'],ignore.case = T)
ind.c <- {tmp<-lapply(input$c, function(x) {which(df[,'Company']==x)}); Reduce(union,tmp)}
ind.l <- if(input$l=='') NULL else grep(input$l,df[,'Location'],ignore.case = T)
ind.d <- which(df[,'Posted']<=input$d)
ind.s <- {tmp<-lapply(input$s, function(x) {which(df[,'Source']==x)}); Reduce(union,tmp)}
ind.all <- list(ind.j,ind.c,ind.l,ind.d,ind.s)
ind <- if(is.null(ind.s)) NULL else {ind.null<- which(lapply(ind.all,is.null)==TRUE) ;Reduce(intersect,ind.all[-ind.null])}
})
#Create a reactive function to return the search results by returning the indices looked up in the index function above
search <- reactive({
df[index(),]
})
#Print the results of the index function above to test if it works properly
output$printIndex <- renderUI({
list(index())
})
#Send the searchresult table to ui.R to print the results of the search function above
output$searchresult <- renderDataTable({
input$action6 #triggered only when button is pressed
if(input$action6==0) return()
else{isolate({
transformed <- transform(search(), Link = paste('<a href = ', shQuote(url), '>', 'Click</a>'))
transformed <- transformed[,c(1:3,5,7,4,6)] #Rearrange columns
transformed[-7] #Remove last column
})
}
}, option=list(autoWidth=FALSE,pageLength=100,
columnDefs = list(list(targets =c(5,6) -1, searchable = FALSE),list(sWidth=c("100px")))))
}
ui <- shinyUI(fluidPage(
#Display datatable filters on top
tags$head(tags$style("tfoot {display: table-header-group;}")),
#Add a title
h1('Power Search'),
#Use the Sidebar layout
sidebarLayout(
sidebarPanel(
#Add various fields for the user in order to search the dataframe
h5('Note: Running the app takes a little while at startup.'),
helpText('Job:'),
textInput('j',''),
helpText('Company:'),
selectizeInput('c','',choices=NULL,multiple=T),
helpText('Location:'),
textInput('l',''),
sliderInput('d','Posted (days ago)',min = 0,max = 60,step = 5,value = 60),
checkboxGroupInput('s','',choices = c('Indeed','Glassdoor'),selected = c('Indeed','Glassdoor')),
actionButton('action6','Search!')
),
mainPanel(
#Display results
htmlOutput('printIndex'),
dataTableOutput('searchresult')
)
)
))
shinyApp(ui = ui, server = server)
【问题讨论】: