schelling segregation model in shiny - r

I tried to run the Schelling segregation model in shiny. I got 3 inputes: number of houses, number of neighbors and alike_preference and sorting should be done within 1000 seconds. The problem is I don't get the output.
Also, I put my renderTable() function both in the eventreactive() and loop, and outside them , but still no output was shown.
library(shiny)
# UI
ui <- fluidPage(
titlePanel("Schelling’s model!"),
sidebarLayout(
sidebarPanel(
sliderInput(inputId = "Ic1",
label = "Number of Houses:",
min = 1,
max = 51,
value =1),
sliderInput(inputId = "Ic2",
label = "Number of Neighbours",
min=0,
max=2000,
step=50,
value = 0),
sliderInput(inputId = 'Ic3',
label = 'alike_preference',
min=0,
max=1,
value=0),
br(),
actionButton(inputId = 'Id8','go',
style="color: #fff; background-color: #428fd6; border-color: #2e6da4")
),
# Main panel for displaying outputs ----
mainPanel(
tableOutput(outputId = "map"),
)
)
)
#Now The cycle of changing places in 1000 seconds
server <- function(input, output) {
grid_activation1 <- reactiveVal()
grid_activation1 <- eventReactive(input$Id8 ,{
input$Ic3
group<-c(rep(0,(input$Ic1*input$Ic1)-input$Ic2,rep(1,input$Ic2/2),rep(2,input$Ic2/2)))
grid <- matrix(sample(group,input$Ic1*Input$Ic1,replace=F), ncol= input$Ic1)
image(grid,col=c("black","red","green"),axes=F)
get_neighbors<-function(coords) {
n<-c()
for (i in c(1:8)) {
if (i == 1) {
x<-coords[1] + 1
y<-coords[2]
}
if (i == 2) {
x<-coords[1] + 1
y<-coords[2] + 1
}
if (i == 3) {
x<-coords[1]
y<-coords[2] + 1
}
if (i == 4) {
x<-coords[1] - 1
y<-coords[2] + 1
}
if (i == 5) {
x<-coords[1] - 1
y<-coords[2]
}
if (i == 6) {
x<-coords[1] - 1
y<-coords[2] - 1
}
if (i == 7) {
x<-coords[1]
y<-coords[2] - 1
}
if (i == 8) {
x<-coords[1] + 1
y<-coords[2] - 1
}
if (x < 1) {
x<-51
}
if (x > 51) {
x<-1
}
if (y < 1) {
y<-51
}
if (y > 51) {
y<-1
}
n<-rbind(n,c(x,y))
}
n
}
for (t in c(1:1000)) {
happy_cells<-c()
unhappy_cells<-c()
for (j in c(1:input$Ic1)) {
for (k in c(1:input$Ic1)) {
current<-c(j,k)
value<-grid[j,k]
if (value > 0) {
like_neighbors<-0
all_neighbors<-0
neighbors<-get_neighbors(current)
for (i in c(1:nrow(neighbors))){
x<-neighbors[i,1]
y<-neighbors[i,2]
if (grid[x,y] > 0) {
all_neighbors<-all_neighbors + 1
}
if (grid[x,y] == value) {
like_neighbors<-like_neighbors + 1
}
}
if (is.nan(like_neighbors / all_neighbors)==FALSE) {
if ((like_neighbors / all_neighbors) < input$Ic3) {
unhappy_cells<-rbind(unhappy_cells,c(current[1],current[2]))
}
else {
happy_cells<-rbind(happy_cells,c(current[1],current[2]))
}
}
else {
happy_cells<-rbind(happy_cells,c(current[1],current[2]))
}
}
}
}
happiness_tracker<-append(happiness_tracker,length(happy_cells)/(length(happy_cells) + length(unhappy_cells)))
rand<-sample(nrow(unhappy_cells))
for (i in rand) {
mover<-unhappy_cells[i,]
mover_val<-grid[mover[1],mover[2]]
move_to<-c(sample(1:input$Ic1,1),sample(1:input$Ic1,1))
move_to_val<-grid[move_to[1],move_to[2]]
while (move_to_val > 0 ){
move_to<-c(sample(1:input$Ic1,1),sample(1:input$Ic1,1))
move_to_val<-grid[move_to[1],move_to[2]]
}
grid[mover[1],mover[2]]<-0
grid[move_to[1],move_to[2]]<-mover_val
}
image(grid,col=c("black","red","green"),axes=F)
# I put output plotting in for loop to see changes Continuously
output$map <- renderTable({
grid_activation1
})
}
})
}
shinyApp(ui = ui, server = server)

Related

Use several selection colors in DT::datatable?

I have set:
output$tableId <-
DT::renderDataTable({DT::datatable(..., selection = "multiple")})
And I would like the background color of the selection to vary depending on of it's the first selection, or the second, etc.
It should be possible to use length(input$tableId_rows_selected) (which is described here) to obtain this behaviour? I'm guessing in combination with creating some CSS modifying this:
.table.dataTable tbody td.active, .table.dataTable tbody tr.active td {
background-color: #007bff;
color: white;
}
I know very little CSS, HTML, and JavaScript, so I find these things difficult.
EDIT 2022-02-14:
After #StéphaneLaurent initial answer below, I want to change my question slightly:
The logic I would prefer the most is:
We have m unique colors. n < m previous rows have been selected.
The n+1th row gets selected and is then coloured in the n+1th color and keeps this color until deselected.
When m rows are currently selected, no more selections are possible. Alternatively, I would also be interested in: When the m+1th row gets selected, it gets coloured in the first color, and other row occupying this color gets deselected. m+1 rows are now chosen, and when the m+2th row gets selected, it gets coloured in the second color, and the other row occupying this color gets deselected. And so on.
Moreover:
Since my app will be running through an iframe on a website, and the underlying data of the app will have 10 to 100 million observations, I think a solution where DT::renderDataTable({...}, server = TRUE) would be good.
I also want the solution to work with the DT::datatable(..., selection = list(mode = "multiple", selected = 1:3, target = "row")) option.
I will try to implement the above using #StéphaneLaurent answer, combined with the tools #YihuiXie illustrate here (app from page linked earlier).
If you use the following CSS, then the first row will be red if you select it, the second will be green, the third will be blue:
#dtable tbody tr.selected:nth-of-type(1) td {
box-shadow: inset 0 0 0 9999px red;
}
#dtable tbody tr.selected:nth-of-type(2) td {
box-shadow: inset 0 0 0 9999px green;
}
#dtable tbody tr.selected:nth-of-type(3) td {
box-shadow: inset 0 0 0 9999px blue;
}
Here dtable is the id.
library(shiny)
library(DT)
css <- "
#dtable tbody tr.selected:nth-of-type(1) td {
box-shadow: inset 0 0 0 9999px red;
}
#dtable tbody tr.selected:nth-of-type(2) td {
box-shadow: inset 0 0 0 9999px green;
}
#dtable tbody tr.selected:nth-of-type(3) td {
box-shadow: inset 0 0 0 9999px blue;
}
"
ui <- fluidPage(
tags$head(
tags$style(
HTML(css)
)
),
br(), br(),
DTOutput("dtable")
)
server <- function(input, output, session) {
output[["dtable"]] <- renderDT({
datatable(iris, selection = "multiple")
})
}
shinyApp(ui, server)
Here is how to generate the CSS for 100 rows with a random color, using the sass package. Save the following scss file, say mystyle.scss:
$s-min: 20;
$s-max: 70;
$l-min: 30;
$l-max: 90;
#for $i from 1 through 100 {
#dtable tbody tr.selected:nth-of-type(#{$i}) td {
box-shadow: inset 0 0 0 9999px hsl(random(360),$s-min+random($s-max+-$s-min),$l-min+random($l-max+-$l-min));
}
}
Now compile it to a CSS file:
library(sass)
sass(sass_file("mystyle.scss"), output = "mystyle.css")
Put the file mystyle.css in the www subfolder of the app, and then include it in the app as follows:
ui <- fluidPage(
tags$head(
tags$link(
href = "mystyle.css", rel = "stylesheet"
)
),
......
EDIT : jQuery solution
library(shiny)
library(DT)
js <- '
var colors = ["red", "green", "blue", "yellow", "purple"];
table.on("select", function(e, dt, type, indexes) {
var count = table.rows({selected: true}).count();
for(var i = 0; i < count; i++) {
$("#dtable tbody tr.selected").eq(i).find("td").css(
"box-shadow", "inset 0 0 0 9999px " + colors[i]
);
}
}).on("deselect", function(e, dt, type, indexes) {
for(var i = 0; i < indexes.length; i++) {
$("#dtable tbody tr").eq(indexes[i]).find("td").css(
"box-shadow", ""
);
}
var count = table.rows({selected: true}).count();
for(var i = 0; i < count; i++) {
$("#dtable tbody tr.selected").eq(i).find("td").css(
"box-shadow", "inset 0 0 0 9999px " + colors[i]
);
}
});
'
ui <- fluidPage(
br(), br(),
DTOutput("dtable")
)
server <- function(input, output, session) {
output[["dtable"]] <- renderDT({
datatable(
iris,
extensions = "Select",
selection = "none",
callback = JS(js),
options = list(
"select" = "multi"
)
)
}, server = FALSE)
}
EDIT: correction of previous edit
Here is the correct JS code:
js <- '
var colors = ["red", "green", "blue", "yellow", "purple"];
var stack = [];
table.on("select", function(e, dt, type, indexes) {
stack.push(indexes[0]);
for(var i = 0; i < stack.length; i++) {
$("#dtable tbody tr").eq(stack[i]).find("td").css(
"box-shadow", "inset 0 0 0 9999px " + colors[i]
);
}
}).on("deselect", function(e, dt, type, indexes) {
var i0 = stack.indexOf(indexes[0]);
$("#dtable tbody tr").eq(stack[i0]).find("td").css(
"box-shadow", ""
);
stack.splice(i0, 1);
for(var i = 0; i < stack.length; i++) {
$("#dtable tbody tr").eq(stack[i]).find("td").css(
"box-shadow", "inset 0 0 0 9999px " + colors[i]
);
}
});
'
EDIT: without the 'Select' extension
js <- '
var colors = ["red", "green", "blue", "yellow", "purple"];
var stack = [];
table.on("click", "tr", function() {
var $rows = $("#dtable tbody tr"); // SIMONSIMON I moved this line
var $row = $(this);
var idx = $row.index();
if($row.hasClass("selected")) {
stack.push(idx);
for(var i = 0; i < stack.length; i++) {
$rows.eq(stack[i]).find("td").css(
"box-shadow", "inset 0 0 0 9999px " + colors[i]
);
}
} else {
var i0 = stack.indexOf(idx);
$rows.eq(stack[i0]).find("td").css(
"box-shadow", ""
);
stack.splice(i0, 1);
for(var i = 0; i < stack.length; i++) {
$rows.eq(stack[i]).find("td").css(
"box-shadow", "inset 0 0 0 9999px " + colors[i]
);
}
}
});
'
......
output[["dtable"]] <- renderDT({
datatable(
iris,
selection = "multiple",
callback = JS(js)
)
}, server = TRUE)
While technically this doesn't do what I originally requested (i.e. changing the selection colouring dynamically), the results from this implementation appear visually similar to the end-user.
The idea behind the solution is to keep track of the row selection counter, update the table via a proxy, and apply conditional formatting.
library(shiny)
library(data.table)
library(DT)
data(iris)
iris <- suppressWarnings(cbind(as.data.table(iris),
currently_selected = numeric(),
selected_as_nr = numeric(),
overwrite = numeric()))
ui <- fluidPage(
dataTableOutput("table"),
)
server <- function(input, output, session) {
iris[, currently_selected := 0]
iris[, selected_as_nr := NA]
iris[, overwrite := 0]
output$table <- DT::renderDataTable({
DT::datatable(iris,
selection = list(mode = "multiple",
selected = 1,
target = "row")) %>%
formatStyle("Sepal.Length",
"selected_as_nr",
backgroundColor = styleEqual(0:4, c("green",
"red",
"black",
"blue",
"yellow")))
})
proxy <- dataTableProxy(outputId = "table")
observeEvent(input$table_rows_selected, {
new_selected_row <- input$table_rows_selected[1]
iris[new_selected_row, currently_selected := (currently_selected + 1) %% 2]
if (iris[new_selected_row, currently_selected] == 1) {
new_selection_nr <- suppressWarnings(iris[, min(setdiff(0:4, unique(selected_as_nr)))])
if (new_selection_nr != "Inf") {
iris[, overwrite := 0]
iris[new_selected_row, selected_as_nr := new_selection_nr]
} else {
overwrite <- iris[, unique(overwrite)]
iris[selected_as_nr == overwrite, currently_selected := 0]
iris[selected_as_nr == overwrite, selected_as_nr := NA]
iris[new_selected_row, selected_as_nr := overwrite]
iris[, overwrite := (overwrite + 1) %% 5]
}
} else {
iris[new_selected_row, selected_as_nr := NA]
}
DT::replaceData(proxy, iris)
})
}
shinyApp(ui, server)

Drawing Customized Square Grids over highchart map in shiny

I have created a simple shiny app where I have country, name, and month as inputs according to which a certain map is plotted.
What I would like to do, is to draw cubic 50*50 km grids over each base map.
I have as data, the coordinates of the centroid of each grid, a certain value to plot per grid (filtered per year and month)
What I have till now, is the filter inputs and the base maps, still have no clue how to dram the grids over the map.
Any help is appreciated
Here is part of my code
dashboardHeader(title=""),
dashboardSidebar(sidebarMenu(
menuItem("",tabName="",icon =icon("dashboard"))
)),
dashboardBody(
tabItem(tabName="",
fluidRow(
box(title="Please choose a country,month and year", width=12,status="warning",solidHeader=TRUE,
selectInput("Country","Country",choices=countries_list, multiple=FALSE),
selectInput("Month","Month",choices=month_list,multiple=FALSE),
selectInput("Year","Year",choices=year_list,multiple=FALSE),
downloadButton("DownloadData","Download Data as csv"))
),
fluidRow(
box(title="Grids",width=12,highchartOutput("Map",height=450),status="primary",solidHeader=TRUE)
)
)
)
)
# Server input/output Function ---------------------------------------------------------
server<-function(input,output){
#Interactive filters & base Maps & Grids
data1<-reactive(
{
req(input$Country)
req(input$Month)
req(input$Year)
data_filtered<- df_Main%>%filter(country %in% input$Country)%>%filter(month_name %in% input$Month)%>%filter(year %in% input$Year)
}
)
output$Map <- renderHighchart(
{
if(input$Country=="Algeria"){
hcmap("https://code.highcharts.com/mapdata/countries/dz/dz-all.js")%>%hc_title(text = "Algeria")
}
else if(input$Country=="Bahrain"){
hcmap("https://code.highcharts.com/mapdata/countries/bh/bh-all.js")%>%hc_title(text = "Bahrain")
}
else if(input$Country=="Comoros"){
hcmap("https://code.highcharts.com/mapdata/countries/km/km-all.js")%>%hc_title(text = "Comoros")
}
else if(input$Country=="Djibouti"){
hcmap("https://code.highcharts.com/mapdata/countries/dj/dj-all.js")%>%hc_title(text = "Djibouti")
}
else if(input$Country=="Egypt"){
hcmap("https://code.highcharts.com/mapdata/countries/eg/eg-all.js")%>%hc_title(text = "Egypt")
}
else if(input$Country=="Iraq"){
hcmap("https://code.highcharts.com/mapdata/countries/iq/iq-all.js")%>%hc_title(text = "Iraq")
}
else if(input$Country=="Jordan"){
hcmap("https://code.highcharts.com/mapdata/countries/jo/jo-all.js")%>%hc_title(text = "Jordan")
}
else if(input$Country=="Kuwait"){
hcmap("https://code.highcharts.com/mapdata/countries/kw/kw-all.js")%>%hc_title(text = "Kuwait")
}
else if(input$Country=="Lebanon"){
hcmap("https://code.highcharts.com/mapdata/countries/lb/lb-all.js")%>%hc_title(text = "Lebanon")
}
else if(input$Country=="Libya"){
hcmap("https://code.highcharts.com/mapdata/countries/ly/ly-all.js")%>%hc_title(text = "Libya")
}
else if(input$Country=="Mauritania"){
hcmap("https://code.highcharts.com/mapdata/countries/mr/mr-all.js")%>%hc_title(text = "Mauritania")
}
else if(input$Country=="Morocco"){
hcmap("https://code.highcharts.com/mapdata/countries/ma/ma-all.js")%>%hc_title(text = "Morocco")
}
else if(input$Country=="Oman"){
hcmap("https://code.highcharts.com/mapdata/countries/om/om-all.js")%>%hc_title(text = "Oman")
}
else if(input$Country=="Qatar"){
hcmap("https://code.highcharts.com/mapdata/countries/qa/qa-all.js")%>%hc_title(text = "Qatar")
}
else if(input$Country=="Saudi Arabia"){
hcmap("https://code.highcharts.com/mapdata/countries/sa/sa-all.js")%>%hc_title(text = "Saudi Arabia")
}
else if(input$Country=="Somalia"){
hcmap("https://code.highcharts.com/mapdata/countries/so/so-all.js")%>%hc_title(text = "Somalia")
}
........
}
)
#Downloadable data .csv format
output$DownloadData <- downloadHandler(
filename = function() {
paste0(Sys.time(), ".csv", sep = "")
},
content = function(file) {
data_filtered<-df_Main %>%filter(month_name %in% input$Month)%>%filter(year %in% input$Year)%>%filter(country %in% input$Country)
write.csv(data_filtered, file)
}
)
}
# Call Server -------------------------------------------------------------
shinyApp(ui,server)```

R Incorrect Number of Dimensions Error from data.frame Assignment

When running the code below I get the error:
Error in data[, 4] : incorrect number of dimensions
Both data[,4] and goals have the same length (480) so I don't understand what the issue is. Data is a data.frame with 4 columns and goals is a length 480 vector.
library(glmmTMB)
simulate_games = function(data) {
mod <- glmmTMB(goals ~ home + (1|attack) + (1|defence), poisson, data=data, REML=TRUE)
goals = predict(mod,newdata = data, type = "response")
data[,4] = goals #Error here
res = comp_ranks(goals)[,2] #comp_ranks is a user defined function
for (i in 1:1000) {
data[,4] = rpois(480,goals)
res = cbind(res,comp_ranks(data)[,2])
}
return(res)
}
long <- read.csv("https://www.math.ntnu.no/emner/TMA4315/2020h/eliteserie.csv", colClasses = c("factor","factor","factor","numeric"))
simulate_games(long)
Here is also the comp_ranks function although I don't think its whats causing the error.
comp_ranks = function(data) {
goals = data[,4]
goals = goals[!is.na(goals)]
teams = unique(data[,1])
teams_points = cbind.data.frame(0,teams)
goals_scored = cbind.data.frame(0,teams)
goals_conceded = cbind.data.frame(0,teams)
for (i in 1:length(teams)) {
tfs = data[,1] == teams[i]
tfc = data[,2] == teams[i]
goals_scored[i,1] = sum(na.omit(goals[tfs]))
goals_conceded[i,1] = sum(na.omit(goals[tfc]))
}
for (i in seq(1,length(goals)-1,2)) {
idx_1 = match(data[,1][i],teams)
idx_2 = match(data[,1][i+1],teams)
if (goals[i] - goals[i+1] > 0) {
teams_points[idx_1,1] = teams_points[idx_1,1] + 3
}
else if (goals[i] - goals[i+1] < 0 ) {
teams_points[idx_2,1] = teams_points[idx_2,1] + 3
}
else {
teams_points[idx_1,1] = teams_points[idx_1,1] + 1
teams_points[idx_2,1] = teams_points[idx_2,1] + 1
}
}
#Sort data.frame by ranks
colnames(teams_points) = c("Points","Teams")
teams_points = teams_points[with(teams_points, order(-Points)), ]
diff = goals_scored[,1] - goals_conceded[,1]
goals_diff = cbind.data.frame(diff,teams)
teams_ranked = teams_points[,2]
for (i in 1:length(teams_points)) {
for (j in 1:length(teams_points)) {
if(j != i) {
if (teams_points[i,1] == teams_points[j,1]) {
if (goals_diff[i,1] == goals_diff[j,1]) {
if (goals_scored[i,1] < goals_scored[j,1] ) {
teams_ranked = replace(teams_ranked,c(i,j), teams_ranked[c(j,i)])
teams_points[,2] = teams_ranked
}
else if(goals_diff[i,1] < goals_diff[j,1] ) {
teams_ranked = replace(teams_ranked,c(i,j), teams_ranked[c(j,i)])
teams_points[,2] = teams_ranked
}
}
}
}
}
}
ranks = data.frame("Ranks" = c(1:16), "Teams" = teams_points[,2], "Points" = teams_points[,1])
return(ranks)
}

Problem getting current list of input values in Shiny

I'm having quite a few problems to get the updated values from several coonditionalPanels. I created a reactive variable parList which should contain the parN_sig input variables. These variables should come from conditional panels and they are all named parN_sig. I do not know why but I always end up getting values from the double_sig panel when another panel is shown at the UI.
Here's my code:
ui.r
jscode <- "
shinyjs.disableTab = function(name) {
var tab = $('.nav li a[data-value=' + name + ']');
tab.bind('click.tab', function(e) {
e.preventDefault();
return false;
});
tab.addClass('disabled');
}
shinyjs.enableTab = function(name) {
var tab = $('.nav li a[data-value=' + name + ']');
tab.unbind('click.tab');
tab.removeClass('disabled');
}
"
css <- "
.nav li a.disabled {
background-color: #aaa !important;
color: #333 !important;
cursor: not-allowed !important;
border-color: #aaa !important;
}"
# Create Shiny object
library(shiny)
library(shinythemes)
library(shinyjs)
library(ggplot2)
library(grid)
library(egg)
# source("input.r")
source("functions.r")
formula_tabs<-tabsetPanel(
tabPanel("double_sig",
withMathJax("$$y=d+\\frac{a}{1+exp^{-b*(t-c)}}+\\frac{e}{1+exp^{-f*(t-g)}}$$")
),
tabPanel("gompertz",
withMathJax("$$y=b*exp^{\\ln(\\frac{c}{b})*exp^{-a*t}}$$")
),
tabPanel("verhulst",
withMathJax("$$y=\\frac{b*c}{b+(b-c)*exp^{-a*t}}$$")
),
id = "formulas",
type = "tabs"
)
fluidPage(useShinyjs(),theme = shinytheme("lumen"),useShinyjs(),tags$style("#params { display:none; } #formulas { display:none; }"),
extendShinyjs(text = jscode),inlineCSS(css),
navbarPage("Protein turnover model",id="tabs",
tabsetPanel(tabPanel("Input data",
checkboxInput("multiple","Single file",value = FALSE),
uiOutput("mult_files"),
uiOutput("sing_file"),
actionButton("disp_distr","Show distributions"),
plotOutput("distr_plot"),
plotOutput("distr_stade")
),
tabPanel("Weight fitting",
fileInput("weight_data","Choose weight data to be fitted",accept = c("text/csv")),
div(style="display:inline-block",selectInput("method_we","Select fitting formula",choices = c("Logistic"="verhulst","Gompertz"="gompertz","Empiric"="empirique","Log polynomial"="log_poly","Double sigmoid"="double_sig"))),
div(style="display:inline-block",formula_tabs), ## "Contois"="contois",,"Noyau"="seed",
conditionalPanel("input.method_we=='verhulst'",textInput("par1_sig","Enter value of a",value =0.1),
textInput("par2_sig","Enter value of b",value = 100),
textInput("par3_sig","Enter value of c",value = 1)),
conditionalPanel("input.method_we=='gompertz'",textInput("par1_sig","Enter value of a",value =0.065),
textInput("par2_sig","Enter value of b",value = 114.39),
textInput("par3_sig","Enter value of c",value = 0.52)),
conditionalPanel("input.method_we=='empirique'",textInput("par1_sig","Enter value of a",value =5.38),
textInput("par2_sig","Enter value of b",value = 8),
textInput("par3_sig","Enter value of c",value = 7)),
conditionalPanel("input.method_we=='double_sig'",textInput("par1_sig","Enter value of a",value = 48),
textInput("par2_sig","Enter value of b",value = 0.144),
textInput("par3_sig","Enter value of c",value = 35),
textInput("par4_sig","Enter value of d",value = 0.4),
textInput("par5_sig","Enter value of e",value = 48),
textInput("par6_sig","Enter value of f",value = 0.042),
textInput("par7_sig","Enter value of g",value = 90)),
actionButton("fit_op","Fit"),
plotOutput("fitplot")
),
tabPanel("mRNA fitting and calculation",
textInput("ksmin","Value of ksmin",value =3*4*3*3.6*24),
selectInput("fit_mrna","Select fitting formula",choices=c("3rd degree polynomial"="3_deg","6th degree polynomial"="6_deg","3rd degree logarithmic polynomial"="3_deg_log")),
actionButton("run_loop","Run calculation"),
disabled(downloadButton("downFile","Save results"))
),
tabPanel("Results",id="tabRes",
uiOutput("select_res"),
plotOutput("fit_prot_plot")
)
))
)
server.r
library(shiny)
library(shinythemes)
library(shinyjs)
library(ggplot2)
library(grid)
library(egg)
# source("input.r")
source("functions.r")
function(input, output, session) {
js$disableTab("tabRes")
fit_op<-reactiveValues(data=NULL)
run_calc<-reactiveValues(data=NULL)
en_but<-reactiveValues(enable=FALSE)
theme<<-theme(panel.background = element_blank(),panel.border=element_rect(fill=NA),panel.grid.major = element_blank(),panel.grid.minor = element_blank(),strip.background=element_blank(),axis.text.x=element_text(colour="black"),axis.text.y=element_text(colour="black"),axis.ticks=element_line(colour="black"),plot.margin=unit(c(1,1,1,1),"line"))
output$mult_files<-renderUI({
if (!input$multiple){
tagList(fileInput("prot_file","Choose protein file"),
fileInput("mrna_file","Choose transcript file"))
}
})
output$sing_file<-renderUI({
if (input$multiple){
tagList(textInput("protein_tab","Name of protein tab",value = "Proteines"),
textInput("rna_tab","Name of mRNA tab",value = "Transcrits"),
fileInput("data_file","Choose xls/xlsx file",accept=c(".xls",".xlsx")))
}
})
observeEvent(input$method_we, {
# updateTabsetPanel(session, "params", selected = input$method_we)
updateTabsetPanel(session,"formulas",selected = input$method_we)
})
observe({
if(!is.null(input$data_file)){
inFile<-input$data_file
list_data<-loadData(inFile$datapath,input$rna_tab,input$protein_tab,poids=F)
mrna_data<-list_data$mrna
prot_data<-list_data$prot
test_list<-list_data$parse
test_list<<-sample(test_list,3)
clean_mrna_data<<-mrna_data[,-which(is.na(as.numeric(as.character(colnames(mrna_data)))))]
clean_prot_data<<-prot_data[,-which(is.na(as.numeric(as.character(colnames(prot_data)))))]
}
})
observe({
if((!is.null(input$prot_file)) & (!is.null(input$mrna_file))){
protFile<-input$prot_file
mrnaFile<-input$mrna_file
prot_data<-loadData(protFile$datapath,"","",poids=F)
mrna_data<-loadData(mrnaFile$datapath,"","",poids=F)
clean_mrna_data<<-mrna_data[,-which(is.na(as.numeric(as.character(colnames(mrna_data)))))]
clean_prot_data<<-prot_data[,-which(is.na(as.numeric(as.character(colnames(prot_data)))))]
total_data<-merge(mrna_data,prot_data)
lista<-vector("list",nrow(mrna_data))
for (i in seq(1,nrow(total_data))){
lista[[i]]<-list("Protein_ID"=total_data[i,"Protein"],"Transcrit_ID"=total_data[i,"Transcrit"],"Transcrit_val"=as.matrix(total_data[i,3:29]),"Protein_val"=as.matrix(total_data[i,30:ncol(total_data)]),"DPA"=t)
}
# test_list<<-lista
test_list<<-sample(lista,3)
}
})
observeEvent(input$disp_distr,{
print("Plotting...")
output$distr_plot<-renderPlot({print(combineGraphs(clean_mrna_data,clean_prot_data,"",moyenne = T))})
print("Finished")
})
# parList<-reactiveValues()
# observe({
# for (i in reactiveValuesToList(input)){
# print(i)
# if (grepl("par[1-9]+_sig",i,perl = T)){
# newlist[[input[[i]]]]<-input[[i]]
# }
# }
# # })
parList<-reactive({
x<-reactiveValuesToList(input)
x_ind<-grep("par[1-9]+",names(x),perl = T)
newlist<-vector("list",length(x_ind))
names(newlist)<-names(x[x_ind])
for (el in names(newlist)){
newlist[[el]]<-as.numeric(as.character(input[[el]]))
}
names(newlist)<-gsub("_sig","",names(newlist))
newlist<-newlist[order(names(newlist))]
newlist
})
observeEvent(input$fit_op,{
browser()
print(parList())
inFile<-input$weight_data
days_kiwi<-rep(c(0,13,26,39,55,76,118,179,222), each = 3)
poids_data<-loadData(inFile$datapath,"","",poids=T)
print("Fitting...")
tryCatch({
coefs_poids<<-fitPoids_v2(poids_data[,1],poids_data[,2],input$method_we,parList())
},
warning = function(warn){
showNotification(paste0(warn), type = 'warning')
},
error = function(err){
showNotification(paste0(err), type = 'err')
})
print(coefs_poids$coefs)
val_mu<-mu(c(poids_data$DPA),input$method_we,coefs_poids$coefs,coefs_poids$formula,dpa_analyse = NULL)
data_mu<-data.frame("DPA"=c(poids_data$DPA),"Mu"=val_mu)
g_mu<<-ggplot(data_mu,aes(x=DPA,y=Mu))+geom_line()+theme+xlab("DPA")+ylab("Growth rate (days^-1)")
fit_op$state<-TRUE
print("Finished!!")
output$fitplot<-renderPlot({
req((fit_op$state)==TRUE,exists("coefs_poids"))
ggarrange(coefs_poids$graph,g_mu,ncol=2)
})
})
observeEvent(input$run_loop,{
if (input$fit_mrna!=""){
ksmin=as.numeric(as.character(input$ksmin))
score=0
cont<-0
poids_coef<<-coefs_poids$coefs
formula_poids<<-coefs_poids$formula
mess<-showNotification(paste("Running..."),duration = NULL,type = "message")
for (el in test_list){
tryCatch({
run_calc$run<-TRUE
cont<-cont+1
print(cont)
norm_data<-normaMean(el$Protein_val,el$Transcrit_val,ksmin)
fittedmrna<<-fit_testRNA(el$DPA,norm_data$mrna,"3_deg")
par_k<-solgss_Borne(el$DPA,as.vector(norm_data$prot),as.numeric(norm_data$ks),score)
par_k[["plot_fit_prot"]]<-plotFitProt(el$DPA,as.vector(norm_data$prot),par_k$prot_fit)
X<-matrice_sens(el$DPA,par_k[["solK"]][,1])
diff<-(par_k[["error"]][["errg"]][1]*norm(as.vector(norm_data$prot),"2"))^2
par_k[["corr_matrix"]]<-matrice_corr(X,length(norm_data$prot),diff)
if (!is.null(par_k)){
test_list[[cont]]$SOL<-par_k
# write.csv(test_list[[cont]][["SOL"]][["solK"]],paste("solK/",paste(test_list[[cont]][["Transcrit_ID"]],"_Sol_ks_kd.csv"),sep = ""))
}
},error=function(e){showNotification(paste0("Protein fitting not achieved for ",el$Transcrit_ID,sep=" "),type = "error",duration = NULL)})
}
valid_res<<-Filter(function(x) {length(x) > 5}, test_list)
print(valid_res[[1]])
mess<-showNotification(paste("Finished!!"),duration = NULL,type = "message")
en_but$enable<-TRUE
}
})
output$downFile<-downloadHandler(
filename = function(){
paste("results_KsKd-",Sys.Date(),".zip",sep="")
},
content = function(file){
owd <- setwd(tempdir())
on.exit(setwd(owd))
files <- NULL;
for (res in valid_res){
fileName<-paste(res[["Transcrit_ID"]],"_Sol_ks_kd.csv",sep = "")
write.csv(res[["SOL"]][["solK"]],fileName)
files<-c(files,fileName)
}
zip(zipfile = file,files = files)
if(file.exists(paste0(file, ".zip"))) {file.rename(paste0(file, ".zip"), file)}
},contentType = "application/zip"
)
observe({
if (en_but$enable){
enable("downFile")
}
})
}
I recently started using Shiny, so any help would be extremely appreciated. Thanks in advance!
Welcome to SO.
You've identified the problem yourself: "...are all named parN_sig". That means you don't have several inputs, you only have one. So you always get the value of (say) input$par2_sig from the first conditional panel regardless of which panel you're trying to access.
You have two options:
Provide unique names for every textInput. That will be a pain. Or...
Use modules. They take a bit of getting used to, but are worth the effrt in the end.
If you set the module up correctly, you'll be able to use the same module for each conditional panel, even though they have different numbers of textinputs.
See this page for help on creating your first module.

Problems with "observe" in Shiny

I am working in a ShinyApp which objective here is to create a selection based on attributes that are generated from an Excel database (the number of attributes may vary). Below is the most important part of my server.R code:
shinyServer(function(input, output, session){
seleciona_planilha <- observe({
dados = input$arquivo
if (is.null(dados))
{
return(NULL)
}
else
{
capturar = names(getSheets(loadWorkbook(dados$datapath)))
updateSelectInput(session,"planilha",choices = capturar)
}
})
carrega_dados <- reactive({
dados = input$arquivo
if (is.null(dados))
{
return(NULL)
}
else{return(read.xlsx(dados$datapath, sheetName = input$planilha))}
})
The first "observe" function above works well in order to select the correct sheet and proceed to analysis with the code below.
rotina <- reactive({
dados = carrega_dados()
tam_dados = length(dados)
pos_ini = 22
vet_comp = vector()
resultados = as.data.frame(matrix(nrow = length(seq(pos_ini,tam_dados,2)), ncol = 10))
nomes = names(dados)
cd = 4
k = 1
amostra = vector()
for(i in 1:length(dados[,1]))
{
if(dados[i,6] == 1)
{
amostra[1] = as.character(dados[i,7])
break
}
}
for(i in 1:length(dados[,1]))
{
if(dados[i,6] == 2)
{
amostra[2] = as.character(dados[i,7])
break
}
}
names(resultados) = c("Name",amostra[1], amostra[2],"NSD",
"Tau","Var(Tau)","D-Prime",
"Var(D-Prime)","IC(D-Prime)","p-value(D-Prime)")
for(i in seq(pos_ini,tam_dados,2))
{
cNSD = 0
c1 = 0
c2 = 0
for(j in 1:length(dados[,i]))
{
if(as.character(dados[j,i]) == " NSD" || as.character(dados[j,i]) == "NSD")
{
cNSD = cNSD + 1
}
if(as.character(dados[j,i]) == "1")
{
c1 = c1 + 1
}
if(as.character(dados[j,i]) == "2")
{
c2 = c2 + 1
}
}
vet_comp = c(c1,cNSD,c2)
resultados[k,1] = nomes[i]
resultados[k,2] = c1
resultados[k,3] = c2
resultados[k,4] = cNSD
resultados[k,5] = round(twoAC(vet_comp)$coefficients[1,1],cd)
resultados[k,6] = round((twoAC(vet_comp)$coefficients[1,2])^2,cd)
resultados[k,7] = round(twoAC(vet_comp)$coefficients[2,1],cd)
resultados[k,8] = round((twoAC(vet_comp)$coefficients[1,2])^2,cd)
if(vet_comp[1] != 0 && vet_comp[2] != 0 && vet_comp[3] != 0)
{
resultados[k,9] = paste("[",round(twoAC(vet_comp)$confint[,1],cd),";",
round(twoAC(vet_comp)$confint[,2],cd),"]")
}
else
{
resultados[k,9] = paste("No IC")
}
resultados[k,10] = round((twoAC(vet_comp)$p.value)/2,cd)
k = k + 1
}
return(resultados)
})
The reactive function "rotina" returns a data.frame. The first column in the data.frame are the attribute names that I would like to use in a selector.
But for some reason I don't know, when I call another "observe" function to get the attribute names and pass to the selector, it not works.
seleciona_atributo <- observe({
resultados = rotina()
atributos = resultados[,1]
updateSelectInput(session,"atributo",choices = atributos)
})
I tried to assign "resultados" as a global variable too, but with no success.
Finally, my ui.R code:
shinyUI(fluidPage(
titlePanel("2-AC Sensory Tool"),
sidebarLayout(
sidebarPanel(
fileInput('arquivo', 'Choose XLS/XLSX File',
accept=c('.xls','.xlsx')),
tags$hr(),
selectInput("planilha",label = h4("Select data sheet"),""),
tags$hr(),
selectInput("atributo",label = h4("Select attribute to generate d-prime graphic",""),
downloadButton('download', 'Download results')
),
mainPanel(
plotOutput("grafico_dp"),
plotOutput("grafico_dist"),
h4("Results Table"),
dataTableOutput("saida")
)
)
))
Thanks in advance!

Resources