Related
When I run a shiny app for portfolio optimization, I get this error ("constraints are inconsistent, no solution") randomly about half the time, while it seems to work correctly half the time. I'm not really sure where the code is going wrong, as I've run the specific solve.QP and quadprog related commands on the console and it works fine there. It's only when I run it on the shiny app that the issue occurs. I suspect it may have something to do with how the code is processing the input, or with how the meq is defined. But I can't tell for sure. I have looked at similar questions on stack overflow but am unsure of how exactly I should change my meq constraints or make the Dmat matrix symmetric (if those two are the issues).
Here's the code:
library(quantmod)
library(lubridate)
library(dplyr)
library(data.table)
library(quadprog)
library(shiny)
Define UI for application that draws a histogram
ui <- fluidPage(
Application title
titlePanel("Robo-Advisor Shiny App"),
Sidebar with a slider inputs
fluidRow(
column(3,
numericInput(
inputId = "start",
label = "Beginning Date (yyymmdd):",
value = 20160101
),
numericInput(
inputId = "end",
label = "Ending Date (yyymmdd):",
value = 20201231
),
selectInput(
inputId = "parameter",
label = "Return optimal portfolio for given:",
choices = c("mu", "vol"),
selected = "mu"
),
numericInput(
inputId = "desired_annual_expected_return",
label = "Desired annual expected return (in decimal format):",
value = 0.2
),
numericInput(
inputId = "desired_annual_vol",
label = "Desired annual vol (in decimal format):",
value = 0.15
)
),
column(9,align="center",
fluidRow(
#splitLayout(div(plotOutput("prcPlot")), div(tableOutput("titleTable"), style = "font-size:100%"), div(tableOutput("prcTable"), style = "font-size:100%"), cellWidths = c("50%", "50%"))
div(plotOutput("prcPlot")),
div(tableOutput("titleTable")),
div(tableOutput("prcTable"))
)
)
) #close fluidRow
)#close fluidPage
Define server logic required to draw a histogram
server <- function(input, output) {
#####PREPARING DATA FOR PLOT & TABLE FUNCTIONS
dataPrep = reactive ({
#define variables from input boxes--------------------
startdt = ymd(input$start)
enddt = ymd(input$end)
parameter = input$parameter
d_mean = input$desired_annual_expected_return
d_sd = input$desired_annual_vol
#download and organize data---------------------------
symbolList = c("MSFT", "WMT", "AAPL", "IBM", "KO")
getSymbols(symbolList, from = startdt, to = enddt, src="yahoo") #default source is finance.yahoo.com
#Convert to dataframe
MSFT = as.data.frame(MSFT)
WMT = as.data.frame(WMT)
AAPL = as.data.frame(AAPL)
IBM = as.data.frame(IBM)
KO = as.data.frame(KO)
MSFT = to.monthly(MSFT) #converts to monthly frequency
WMT = to.monthly(WMT)
AAPL = to.monthly(AAPL)
IBM = to.monthly(IBM)
KO = to.monthly(KO)
prices = cbind(MSFT$MSFT.Adjusted, WMT$WMT.Adjusted, AAPL$AAPL.Adjusted,
IBM$IBM.Adjusted, KO$KO.Adjusted)
len = dim(prices)[1]
returns = as.data.frame(prices[2:len,] / prices[1:(len-1),]) - 1
names(returns) = c("msft", "wmt", "aapl", "ibm", "ko")
#Define the mean-variance optimization function
QPoptim = function(Eport, noshort, N, muvec, covmat){
ones = array(1,N)
Dmat = covmat
dvec = array(0,N)
Amat = cbind(muvec, ones)
b0vec = c(Eport, 1)
if(noshort==1) {
idmat = matrix(0,N,N)
diag(idmat) = 1
Amat = cbind(Amat,idmat)
b0vec = c(b0vec, array(0,N))
}
wvec = solve.QP(Dmat, dvec, Amat, b0vec, meq=2)$solution
sigport = sqrt( t(wvec) %*% covmat %*% wvec ) #returns this last value
}
#repeating the Qpoptim code partly to get only the portfolio weights
meanvarweights = function(Eport, noshort, N, muvec, covmat){
ones = array(1,N)
Dmat = covmat
dvec = array(0,N)
Amat = cbind(muvec, ones)
b0vec = c(Eport, 1)
if(noshort==1) {
idmat = matrix(0,N,N)
diag(idmat) = 1
Amat = cbind(Amat,idmat)
b0vec = c(b0vec, array(0,N))
}
wvec = solve.QP(Dmat, dvec, Amat, b0vec, meq=2)$solution
}
#initialize
N = 5
muvec = colMeans(returns[,1:N])
covmat = var(returns[,1:N])
#scroll through Eport values to derive efficient frontier
mincut = min(muvec)
maxcut = max(muvec)
Eportvec = seq(mincut,maxcut,length=300)
sigportvec = unlist(lapply(Eportvec, QPoptim, noshort=1, N, muvec, covmat))
#annualize stats
sigportvec = sigportvec * sqrt(12)
Eportvec = Eportvec * 12
#defining efficient frontier---------------------------------------------------
Emincut = Eportvec[which(sigportvec==min(sigportvec))]
idx = which(Eportvec>=Emincut)
#selecting the optimal portfolio
if (parameter=="mu") {
muportvec=c(d_mean)
w1 = meanvarweights(Eport=muportvec[1]/12, noshort=1, N, muvec, covmat)
sig1 = sqrt( t(w1) %*% covmat %*% w1 ) * sqrt(12)
} else {
sigportvec_1 = sigportvec[idx]
Eportvec_1 = Eportvec[idx]
a = which(abs(sigportvec_1-d_sd)==min(abs(sigportvec_1-d_sd)))
muportvec = c(Eportvec_1[a])
w1 = meanvarweights(Eport=(muportvec[1]/12), noshort=1, N, muvec, covmat)
sig1 = sqrt( t(w1) %*% covmat %*% w1 ) * sqrt(12)
}
#return data for output function-----------------------
temp = list(Eportvec = Eportvec, sigportvec = sigportvec,
w1=w1, muportvec=muportvec,sig1=sig1,idx=idx)
})
#####Plotting frontier
output$prcPlot <- renderPlot({
#calls above function for prepped data------------------------------
temp = dataPrep()
sigportvec = temp$sigportvec
Eportvec = temp$Eportvec
muportvec = temp$muportvec
w1 = temp$w1
sig1 = temp$sig1
idx= temp$idx
#define variables from input boxes----------------------------------
startdt = ymd(input$start)
enddt = ymd(input$end)
parameter = input$parameter
d_mean = input$desired_annual_expected_return
d_sd = input$desired_annual_vol
#text heading of plot
startdt_txt = format(startdt, "%Y-%m-%d")
enddt_txt = format(enddt, "%Y-%m-%d")
str1 = "Efficient Frontier (based on data from)"
str2 = "to"
main_text_string = paste(str1,startdt_txt,str2,enddt_txt)
#plots all minimum variance portfolios------------------------------------------
plot(sigportvec, Eportvec,
xlim=c(0,max(sigportvec)), ylim=c(0,max(Eportvec)),
type="l", xlab="sigma", ylab="E(r)",
main=main_text_string, col = "black", lwd=1, lty="dashed")
#now just plot efficient frontier on top------------------------------------------
lines(x=sigportvec[idx], y=Eportvec[idx], type="l", col = "blue", lwd=2)
#point label text
sig1_d = format(round(sig1,2), nsmall = 2)
muportvec_d = format(round(muportvec,2), nsmall = 2)
sig1_t = as.character(sig1_d)
muportvec_t = as.character(muportvec_d)
sig1_txt = paste("sig=",sig1_t)
muportvec_txt = paste("mu=",muportvec_t)
label1 = paste(sig1_txt, ",", muportvec_txt)
#pick a portfolio along efficient frontier-----------------------
points(x=c(sig1), y=muportvec, col="blue", lwd=3, pch=1)
text(x=c(sig1), y=muportvec, labels = c(label1), pos=4)
})
#Making table heading
output$titleTable <- renderTable({
#calls above function for prepped data------------------------------
temp = dataPrep()
sigportvec = temp$sigportvec
Eportvec = temp$Eportvec
muportvec = temp$muportvec
w1 = temp$w1
sig1 = temp$sig1
idx= temp$idx
#define variables from input boxes----------------------------------
startdt = ymd(input$start)
enddt = ymd(input$end)
parameter = input$parameter
d_mean = input$desired_annual_expected_return
d_sd = input$desired_annual_vol
#Prepare table heading format
sig1_d = format(round(sig1,2), nsmall = 2)
muportvec_d = format(round(muportvec,2), nsmall = 2)
if (parameter=="mu") {
string1 <- "The following portfolio achieves your desired annual mu ="
string2 <- "with vol ="
result = paste(string1, muportvec_d, string2, sig1_d)
} else {
string1 <- "The following portfolio achieves your desired annual vol ="
string2 <- "with mu ="
result = paste(string1, sig1_d, string2, muportvec_d)
}
#making table
colnamevec = c(" ")
numcol = length(colnamevec)
blank = array("", numcol)
blank = as.data.frame(t(blank))
colnames(blank) = colnamevec #prepared so that header of output is empty
row1 = blank
row1[1] = c(result)
ltemp = list(row1)
FINALOUT = rbindlist(ltemp) #prints this final table
}, align = 'c')
#####Plotting Summary Table
output$prcTable <- renderTable({
#calls above function for prepped data------------------------------
temp = dataPrep()
sigportvec = temp$sigportvec
Eportvec = temp$Eportvec
muportvec = temp$muportvec
w1 = temp$w1
sig1 = temp$sig1
idx= temp$idx
#define variables from input boxes----------------------------------
startdt = ymd(input$start)
enddt = ymd(input$end)
parameter = input$parameter
d_mean = input$desired_annual_expected_return
d_sd = input$desired_annual_vol
#reducing decimal places in the weight values
w1_d = format(round(w1,2),nsmall=2)
#making table
colnamevec = c(" ", " ")
numcol = length(colnamevec)
blank = array("", numcol)
blank = as.data.frame(t(blank))
colnames(blank) = colnamevec #prepared so that header of output is empty
row1 = blank
row2 = blank
row3 = blank
row4 = blank
row5 = blank
row1[1:2] = c("MSFT",w1_d[1])
row2[1:2] = c("WMT",w1_d[2])
row3[1:2] = c("AAPL",w1_d[3])
row4[1:2] = c("IBM",w1_d[4])
row5[1:2] = c("KO",w1_d[5])
ltemp = list(row1, row2, row3, row4, row5)
FINALOUT = rbindlist(ltemp) #prints this final table
}, align = 'cc')
}
Run the application
shinyApp(ui = ui, server = server)
Here is my code I have 3 different questions, I searched evrywhere and tryied sooo many things, but it always gave me an error .
First how can I add a function to save my rglwidgetoutput to any file ?
And also mby save the log .
Secound: If I open the program it always opens a small "focus" window, can I somehow remove that ?
And last but not least, I have a Log , and I want to rename the data_planes so the logfile looks better :)
#######################################################################################
# Install librarys #
#######################################################################################
#install.packages("shiny")
#install.packages("rgl")
#install.packages("shinythemes")
#install.packages("devtools")
library(shiny)
library(rgl)
library(shinythemes)
library(devtools)
#install_github("rgl", "trestletech", "js-class")
#install_github("rgl", "trestletech", "js-class")
#######################################################################################
# User Interface #
#######################################################################################
ui <- fluidPage(theme = shinytheme("slate"),
headerPanel("Block Theory"),
sidebarPanel(
numericInput(inputId = "dd", label = "Dip direction:", value = "", width = "80%", min = 0, max = 360),
numericInput(inputId = "fa", label = "Fracture angle:", value = "", width = "80%", min = 0, max = 90),
numericInput(inputId = "position_x", label = "Position:", value = "", width = "40%"),
numericInput(inputId = "position_y", label = "", value = "", width = "40%"),
numericInput(inputId = "position_z", label = "", value = "", width = "40%"),
#selectInput("form", "Form:",
# c("Circle", "Square", "Ellipsoid")),
actionButton(inputId = "add", label = "Add a plane"),
actionButton(inputId = "plotbutton", label = "Update")
),
mainPanel(
tabsetPanel(
tabPanel("Plot", rglwidgetOutput(outputId = "plot")), # Output
tabPanel("Log", verbatimTextOutput(outputId = "log_planes")), # Log File
# OPTIONS :
tabPanel("Preferences",
checkboxInput("axes_lim", "axes min / max"),
conditionalPanel(
condition = "input.axes_lim == true",
splitLayout(
numericInput(inputId = "min_x", label = "x min:", value = "0", width = "90%"),
numericInput(inputId = "max_x", label = "x max:", value = "1000", width = "90%")),
splitLayout(
numericInput(inputId = "min_y", label = "y min:", value = "0", width = "90%"),
numericInput(inputId = "max_y", label = "y max:", value = "1000", width = "90%")),
splitLayout(
numericInput(inputId = "min_z", label = "z min:", value = "0", width = "90%"),
numericInput(inputId = "max_z", label = "z max:", value = "1000", width = "90%"))),
checkboxInput("axes", "Change axes ratio"),
conditionalPanel(
condition = "input.axes == true",
sliderInput("x_axis", "x axis:",min = 0, max = 1, value = 1, step = 0.1),
sliderInput("y_axis", "y axis:",min = 0, max = 1, value = 1, step = 0.1),
sliderInput("z_axis", "z axis:",min = 0, max = 1, value = 1, step = 0.1)),
checkboxInput("theme", "Change shiny theme"),
conditionalPanel(
condition = "input.theme == true",
shinythemes::themeSelector() )
))
) # /Main panel
) # /ui
#######################################################################################
# SERVER #
#######################################################################################
server <- function(input, output) {
data_planes <- data.frame()
makeReactiveBinding("data_planes")
observe({
input$add
isolate({
data_planes <<- rbind(data_planes, data.frame(input$dd, input$fa , input$position_x , input$position_y , input$position_z))
data_planes <<- na.omit(data_planes)
})
})
output$plot <- renderRglwidget({
input$plotbutton
isolate({
####################################################
# Open 3d plot:
x<-sample(input$min_x:input$max_x, 100)
y<-sample(input$min_y:input$max_y, 100)
z<-sample(input$min_z:input$max_z, 100)
plot3d(x, y, z, type = "n",xlim = c(min(x), max(x)), ylim = c(min(y), max(y)), zlim = c(min(z), max(z),expand = 1.03))
aspect3d(input$x_axis , input$y_axis , input$z_axis)
####################################################
i=1;
while (i <= nrow(data_planes)) {
phi <- data_planes[i,1] * pi / 180
theta <- data_planes[i,2] * pi / 180
Px <- data_planes[i,3]
Py <- data_planes[i,4]
Pz <- data_planes[i,5]
n <- c(sin(theta)*sin(phi), sin(theta) * cos(phi), cos(theta))
# n <- c(-sin(theta)*sin(phi), sin(theta) * cos(phi), -cos(theta))
P_n <- cos(phi)*sin(theta)*Px+(sin(phi)*sin(theta))*Py+cos(phi)*Pz # d = -P * n
# planes3d() plots equation: a*x + b*y + c*z + d = 0
a <- -sin(theta)*sin(phi)
b <- sin(theta) * cos(phi)
c <- -cos(theta)
d <- P_n
cols<-rgb(runif(5),runif(5),runif(5)) #random color genarator
i <- i + 1
planes3d(a, b, c , d , col = cols, alpha = 0.6)
}
rglwidget() # opens the plot inside of main panel
})
})
output$log_planes <- renderPrint(data_planes)
}
#######################################################################################
shinyApp(ui = ui, server = server
)
It's not easy to save rgl output to a PDF. You can save it to an html page using code like this:
htmlwidgets::saveWidget(rglwidget(), file = "rgl.html")
This will fail if it can't find Pandoc; you can use
htmlwidgets::saveWidget(rglwidget(), file = "rgl.html", selfcontained = FALSE)
without Pandoc, but it will create both the HTML file and a subdir of supporting files.
The little window you're seeing is probably the rgl output window. If you never want to see that, run
options(rgl.useNULL = TRUE)
before loading the rgl package. This is a good idea on a Shiny app, because they may be running on a server somewhere and you don't want to try to open an rgl window there.
Sorry, I don't really understand your third question.
I can not figure out what is wrong with the following code. After running runApp('script.R'), I am getting the following error Error: object 'data_survival_curve' not found. I run debug in RStudio and on line nr 60 this variable is created and it exists till the moment when error comes.
script.R file:
library(shiny)
library(survival)
library(survminer)
library(directlabels)
data <- read.csv('dataset.csv', header = TRUE, sep = ",", fileEncoding="UTF-8")
unique_transplant_years_decreasing <- as.numeric(sort(unique(c(data$transplant_year)), decreasing = TRUE))
krivkaPreziti <- sidebarLayout(
# all inputs for graph survival analysis (krivka preziti)
sidebarPanel(
sliderInput("krivka_preziti_input_years", 'Years:',
min = unique_transplant_years_decreasing[length(unique_transplant_years_decreasing)],
max = unique_transplant_years_decreasing[1],
value = c(unique_transplant_years_decreasing[length(unique_transplant_years_decreasing)],
unique_transplant_years_decreasing[1]),
step = 1),
numericInput('krivka_preziti_input_seskupit_po', 'Group by (years):',
value = 0,
min = 0),
checkboxInput('krivka_preziti_input_facet', 'Facet', value = FALSE),
width = 3
),
# Create a spot for bar plot
mainPanel(
h2('Survival curve'),
br(),
plotOutput('krivka_preziti', height = "750px"),
width = 12
)
)
panelAnalyzaPreziti <- tabPanel(
'Survival analysis',
krivkaPreziti
)
ui <- navbarPage(
title = "Application",
panelAnalyzaPreziti
)
server <- shinyServer(
function(input, output, session)
{
output$krivka_preziti <- renderPlot(
{
krivka_year_bottom <- input$krivka_preziti_input_years[1]
krivka_year_top <- input$krivka_preziti_input_years[2]
krivka_seskupit_po <- input$krivka_preziti_input_seskupit_po
# data which fit the range of selected years
# data which meet the condition that survival_time is not NA
data_survival_curve <- data[data$transplant_year %in% seq(krivka_year_bottom, krivka_year_top) &
!is.na(data$survival_time) &
data$survival_time >= 0,]
# if seskupit_po != 0, then cut
if(krivka_seskupit_po != 0) {
data_survival_curve$time_period <- cut(as.numeric(data_survival_curve$transplant_year),
seq(krivka_year_bottom, krivka_year_top, krivka_seskupit_po),
include.lowest = T)
data_survival_curve <- data_survival_curve[!is.na(data_survival_curve$time_period),]
data_survival_curve$time_period <- as.factor(data_survival_curve$time_period)
}
else {
data_survival_curve$time_period = data_survival_curve$transplant_year
}
# validate number of rows of data set > 0
shiny::validate(
need(nrow(data_survival_curve) > 0, 'Broader your input')
)
surv_obj <- Surv(data_survival_curve$survival_time/365,data_survival_curve$patient_died)
fit <- survfit(surv_obj ~ time_period, data = data_survival_curve)
krivka_preziti_plt <- ggsurvplot(fit,
linetype = c('solid'),
ggtheme = theme_bw(),
surv.scale = 'percent',
xlab = 'Years',
ylab = '%',
censor = FALSE,
break.x.by = 1,
break.y.by = 0.1)
plot2 <- krivka_preziti_plt + geom_dl(aes(label = time_period), method = list("last.points"), cex = 0.8)
plot2
}
)
}
)
shinyApp(
ui = ui,
server = server
)
Here is the data set that I am using: enter link description here
I've been struggling with the same issue since almost 1 hour and finally found the solution !
There have been a change in the "ggsurvplot" function and you now need to specify the dataset used in the "fit" element. So in your code you have to add :
krivka_preziti_plt <- ggsurvplot(fit, data = data_survival_curve,
linetype = c('solid'),
ggtheme = theme_bw(),
surv.scale = 'percent',
xlab = 'Years',
ylab = '%',
censor = FALSE,
break.x.by = 1,
break.y.by = 0.1)
Source : Github Issue, 13th of January 2018
I' trying to modify pch parameter of plot by inserting an input from selectInput:
selectInput("points", "Points:",
list("Job lost" = "joblost",
"Sex" = "sex",
))
into
output$Plot <- renderPlot({
plot(as.formula(formula()),data=Benefits,
main = caption(), pch = as.numeric(input$points),
col=as.numeric(input$points))
})
Unfortunately, I get an error: cannot coerce type 'closure' to vector of type 'double'. What steps should I take to fix this ? Of course, both joblost and sex are factors.
Full code:
library(shiny)
library(Ecdat)
attach(Benefits)
u <- shinyUI(pageWithSidebar(
headerPanel("Social benefits"),
sidebarPanel(
selectInput("variable1", "Zmienna X:",
list("Bezrobocie" = "stateur",
"Max zasilek" = "statemb",
"Wiek" = "age",
"Staz w bezrobociu" = "tenure",
"Replacement rate" = "rr"
)),
selectInput("variable2", "Zmienna Y:",
list("Bezrobocie" = "stateur",
"Max zasilek" = "statemb",
"Wiek" = "age",
"Staz w bezrobociu" = "tenure",
"Replacement rate" = "rr"
)),
selectInput("points", "Punkty:",
list("Powod utraty pracy" = "joblost",
"Plec" = "sex",
"Nie-bialy" = "nwhite",
">12 lat szkoly" = "school12",
"Robotnik fizyczny" = "bluecol",
"Mieszka w miescie" = "smsa",
"Zonaty" = "married",
"Ma dzieci" = "dkids",
"Male dzieci" = "dykids",
"Glowa rodziny" = "head",
"Otrzymuje zasilki" = "ui"
)),
checkboxInput("reg", "Pokaz krzywa regresji", FALSE)
),
mainPanel(
plotOutput("Plot")
)
))
s <- shinyServer(function(input, output)
{
formula <- reactive({paste(input$variable2,"~",input$variable1)})
caption <- renderText({formula()})
pkt <- reactive({input$points})
#pkt <- renderText({paste(input$points)})
output$Plot <- renderPlot({
plot(as.formula(formula()),data=Benefits,
main = caption(), pch = as.numeric(input$points),
col=as.numeric(input$points))
if(input$reg == TRUE){
abline(lm(as.formula(formula())),col ="red", lwd = 2)
legend("topleft",inset = 0.02, legend = "Krzywa regresji",
col="red",lty = 1, lwd = 2)
}
})
})
shinyApp(u,s)
The issue was resolved by using a switch in selectInput:
pkt <- reactive({
switch(input$points,
"Powod utraty pracy" = joblost,
"Plec" = sex,
"Nie-bialy" = nwhite,
">12 lat szkoly" = school12,
"Robotnik fizyczny" = bluecol,
"Mieszka w miescie" = smsa,
"Zonaty" = married,
"Ma dzieci" = dkids,
"Male dzieci" = dykids,
"Glowa rodziny" = head,
"Otrzymuje zasilki" = ui)
})
txt <- renderText({paste(input$points)})
output$Plot <- renderPlot({
plot(as.formula(formula()),data=Benefits,
main = caption(), pch = as.numeric(pkt()),
col=as.numeric(pkt()))
I created a shiny app, in which I want to display the residual of a log-linear model using a mosaic plot. I need to use the data from a reactive expression and pass it to loglm. It seem pretty strait forward, but when I do that I get the following error : "objet 'mod' introuvable".
I've already figured which line is causing the problem, but I don't know how to fix it. Running the code below as is should work fine.
However, uncomment the line # mod <- loglm( formula = reformulate(f), data = mod ), in server and you should get the same error I get.
Any help would be greatly appreciated.
ui <- fluidPage(
titlePanel("Shiny Viz!"),
fluidRow( class= "R1",
tabsetPanel(type= "pills",
tabPanel("Log-linear model",
fluidRow(
column(3, offset=1,
selectInput("model", label= "Choose model to fit:",
choices= c("(SPT)","(SP,ST,PT)","(ST,PT)","(SP,PT)","(SP,ST)")),
selectInput("type", label= "Visualise the expected or observed values?",
choices = c("observed", "expected")),
sliderInput("n_breaks", label = "Degree Celcius per bin:",
min = .5, max = 5, value = 1, step = .5)),
column(8, plotOutput("loglinear.mosaic", height= "600px") )
))))
)
library(ggplot2)
library(data.table)
library(vcd)
library(vcdExtra)
server <- function(input, output) {
# Create data
DF <- data.table( Temp = runif(5000, 0, 30),
Presence = factor(rbinom(5000, 1, runif(20, 0.1, 0.60))),
Period = factor(as.integer(runif(5000, 1, 9))) )
# Reactive expression
loglinear <- reactive({
DF[ , Temperature.category := cut_interval(Temp, length= input$n_breaks)]
Tab <- xtabs(formula= ~ Period + Temperature.category + Presence,
data = DF)
return(Tab)
})
# mosaic plot
output$loglinear.mosaic <- renderPlot({
mod <- loglinear()
f <- switch(input$model,
"(SPT)"= c("Presence*Period*Temperature.category"),
"(SP,ST,PT)" = c("Presence*Period","Presence*Temperature.category","Period*Temperature.category"),
"(ST,PT)" = c("Presence*Temperature.category","Period*Temperature.category"),
"(SP,PT)" = c("Presence*Period","Period*Temperature.category"),
"(SP,ST)" = c("Presence*Period","Presence*Temperature.category"))
# mod <- loglm( formula = reformulate(f), data = mod )
mosaic(mod,
gp= shading_hcl,
spacing = spacing_highlighting,
type= input$type,
labeling_args= list(offset_varnames = c(right = 1, left=.5),
offset_labels = c(right = .1),
set_varnames = c(Temperature.category="Temperature", Period="Period",
Presence="Status")),
set_labels=list(Presence = c("Ab","Pr")),
margins = c(right = 5, left = 3, bottom = 1, top =3))
})
}
shinyApp(ui = ui, server = server)
I still haven't found what is causing the problem with loglm, but I've figured another way of getting the result I wanted.
I used glm to fit the model instead of loglm, then used mosaic.glm from the vcdExtra package to create the mosaic plot. The code is pretty much the same except that the data as to be a data.frame and the column 'Temperature.category', 'Period' and 'Presence' must be factor to be used with glm.
However, I am still clueless as to why loglm can't find the object 'mod', but glm can? I'd realy want to know the reason. Since my answers doesn't answer that question, I'll accept an other answer if someone has an explanation.
Here's what the code using glm:
ui <- fluidPage(
titlePanel("Shiny Viz!"),
fluidRow( class= "R1",
tabsetPanel(type= "pills",
tabPanel("Log-linear model",
fluidRow(
column(3, offset=1,
selectInput("model", label= "Choose model to fit:",
choices= c("(SPT)","(SP,ST,PT)","(ST,PT)","(SP,PT)","(SP,ST)")),
selectInput("type", label= "Visualise the expected or observed values?",
choices = c("observed", "expected")),
sliderInput("n_breaks", label = "Degree Celcius per bin:",
min = .5, max = 5, value = 1, step = .5)),
column(8, plotOutput("loglinear.mosaic", height= "800px") )
))))
)
library(ggplot2)
library(data.table)
library(vcd)
library(vcdExtra)
server <- function(input, output) {
DF <- data.table( Temp = runif(5000, 0, 30),
Presence = factor(rbinom(5000, 1, runif(20, 0.1, 0.60))),
Period = factor(as.integer(runif(5000, 1, 9)) ) )
# data to data.frame format
loglinear <- reactive({
DF[ , Temperature.category := cut_interval(Temp, length= input$n_breaks)]
# add 'Freq' column
dat <- data.frame(as.table(xtabs(formula= ~ Period + Temperature.category + Presence,
data = DF)), stringsAsFactors = T)
return(dat)
})
# mosaic plot
output$loglinear.mosaic <- renderPlot({
mod <- loglinear()
f <- switch(input$model,
"(SPT)"= c("Presence*Period*Temperature.category"),
"(SP,ST,PT)" = c("Presence*Period","Presence*Temperature.category","Period*Temperature.category"),
"(ST,PT)" = c("Presence*Temperature.category","Period*Temperature.category"),
"(SP,PT)" = c("Presence*Period","Period*Temperature.category"),
"(SP,ST)" = c("Presence*Period","Presence*Temperature.category"))
# fit model using glm
mod.glm <- glm(formula = reformulate(f, response = "Freq"), data= mod, family= poisson)
mosaic.glm(mod.glm,
formula = ~ Temperature.category + Period + Presence,
gp= shading_hcl,
spacing = spacing_highlighting,
type= input$type,
labeling_args= list(rot_labels = c(left = 0, right = 0),
offset_varnames = c(left=1.5, right = 1),
offset_labels = c(left=.5, right = .1),
set_varnames = c(Temperature.category="Temperature", Period="Period",
Presence="Status")),
set_labels=list(Presence = c("Ab","Pr")),
margins = c(right = 5, left = 4, bottom = 1, top =3))
})
}