I am currently working on a Shiny dashboard that has a slider that outputs the optimal portfolio weights of stocks, gold and silver for a given volatility value using the slider input. I have been able to output the values with a dynamic text output given the slider input, but I cannot figure out how to turn these values into a graph as the text output in Shiny seems to require a function. How can I add a pie chart to this code using the values I get from slidervalues()? It outputs a list of 5 numerical values, now I want to chart the first 3 of them in a pie chart:
library(shiny)
shinyUI(fluidPage(
headerPanel(title = "Volatility Slider"),
sidebarLayout(
sidebarPanel(
sliderInput("Risk","Volatility", 0, 0.24, 0.12)
),
mainPanel(
textOutput("Output")
)
)
))
server <- function(input, output) {
sliderValues <- reactive({
#This part finds the optimal portfolio using CAPM(which is found in a different script).
custom <- three_assets %>%
filter(sd_p > input$Risk,
sd_p < input$Risk+0.0001)
max_er_custom <- custom[custom$er_p == max(custom$er_p)]
toString(max_er_custom)
})
output$Output <- renderText({
sliderValues()
})
}
Here is a screenshot of the dashboard. The first three values are the weights of the three assets, the forth value is the expected return of that portfolio and the last value is the volatility of that portfolio all using historical data.
Not sure how to replicate your logic without your files, but here's an example where the input slider determines the values in the sliderValues data frame, which are in turn used to create a bar chart.
library(shiny); library(ggplot2)
ui <- fluidPage(
headerPanel(title = "Volatility Slider"),
sidebarLayout(
sidebarPanel(
sliderInput("Risk","Volatility", 0, 0.24, 0.12)
),
mainPanel(
plotOutput("Output")
)
)
)
server <- function(input, output) {
sliderValues <- reactive({
data.frame(values = c(input$Risk, 0.7 * (1 - input$Risk), 0.3 * (1-input$Risk)),
categories = c("A", "B", "C"))
})
output$Output <- renderPlot(
ggplot(sliderValues(), aes(1, values, fill = categories)) +
geom_col() +
coord_polar(theta = "y")
)}
shinyApp(ui = ui, server = server)
Related
I want to design a reactive interaction graph for a time series for shiny.
It is used for when I have a time series. I change the first point of the time series.
Then I can get the reactive graph changed for the point changed.
I have trouble for how to assign the value input into the function. Specifically, for the
yinput<-sensi(num). I want to the input be some number range from 0.1 to 0.9.but my sensitive's
function only allow to enter one input.
Is there any idea for that?
Thanks
library(ggplot2)
sensi<-function(input)
{
y<-c(input,5,12,21,30,50,90,100)
return(y)
}
Date = c("2020/07/16","2020/07/23","2020/07/30","2020/08/06","2020/08/13","2020/08/20","2020/08/27","2020/09/13")
num<-c(0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9)
yinput<-sensi(num)
df <- data.frame(yinput, Date = as.Date(Date))
ui <- fluidPage(
titlePanel(title=h4("plot1", align="center")),
sidebarPanel(
sliderInput("num", "Number:",min = 0, max = 0.9,value=0.5)),
mainPanel(plotOutput("plot2")))
server <- function(input,output){
dat <- reactive({
test <- df[df$num %in% seq(from=min(input$num),to=max(input$num),by=1),]
print(test)
test
})
output$plot2<-renderPlot({
ggplot(df) + aes(Date, y) + geom_line()})}
shinyApp(ui, server)
Here's a very basic example
You should be doing your 'thinking' inside your 'server' function.
Hopefully this example will show you how reactive inputs and outputs relate to each other, and you can extend it to your plot.
require(shiny)
ui <- fluidPage(
sliderInput("num", "Number:", min = 0.1, max = 0.9, value = 0.5),
textOutput("number_display")
)
server <- function(input, output){
output$number_display <-
renderText({
as.character(input$num)
})
}
shinyApp(ui = ui, server = server)
Where I've said as.character(input$num), you'll want to do something with num to make your plot.
I want to start a shiny app for practice where a use can choose from a dropdown the values in the "cut" column from the diamonds dataset (from ggplot2).
My ui looks as following:
library(shiny)
# Define UI for application that draws a histogram
shinyUI(fluidPage(
# Application title
titlePanel("Reactive Boxplot"),
# Show a boxplot of the selected cut
mainPanel(
selectInput("column", label = h3("Column to plot"),
choices = c("", diamonds$cut),
selected = 1,
width='55%',
multiple = FALSE),
plotOutput("diamondshist")
)
)
)
I don't know how to define the input variables as the five distinct values in the "cut" column of diamonds dataset. Any input on this?
My server file looks like shared below. I assume I would also need to adapt the input data for the plot.
library(shiny)
library(ggplot2)
# Define server logic required to draw a histogram
shinyServer(function(input, output) {
compute_plot <- reactive({
if (input$column != ""){
ggplot(diamonds[, input$column])+
labs(title = "From diamonds dataset")+
geom_boxplot(aes(x = cut, y = price))+
scale_y_reverse()
}
})
output$diamondshist <- renderPlot({
compute_plot();
})
})
I assume this is what you are after:
pass the levels of diamonds$cut as input selection
subset the diamonds dataset to the selected cut
library(shiny)
library(ggplot2)
# Define UI for application that draws a histogram
ui=shinyUI(fluidPage(
# Application title
titlePanel("Reactive Boxplot"),
# Show a boxplot of the selected cut
mainPanel(
selectInput("column", label = h3("Column to plot"),
choices = c("", levels(diamonds$cut)),
selected = NULL,
width='55%',
multiple = FALSE),
plotOutput("diamondshist")
)
)
)
# Define server logic required to draw a histogram
server=shinyServer(function(input, output) {
compute_plot <- reactive({
if (input$column != ""){
ggplot(subset(diamonds, cut==input$column))+
labs(title = "From diamonds dataset")+
geom_boxplot(aes(x = cut, y = price))+
scale_y_reverse()
}
})
output$diamondshist <- renderPlot({
compute_plot();
})
})
shinyApp(ui = ui, server = server)
I am working on a shiny app where I allow a user to select the plotting criteria and then also allow them to brush the plot and see their selection in a table below. I have some NA values in my data. I have noticed that these NAs end up in my brushed point table as full rows of NA. I can remove these manually with something like this. However, I was wondering if I perhaps was doing something wrong on my brush that was causing this.
Code with a working example is below. I have also included an image of a brush selection demonstrating what I mean.
library(shiny)
library(tidyverse)
# replace some random values in mtcars with NA
set.seed(1)
mtnew <-
as.data.frame(lapply(mtcars, function(m)
m[sample(
c(TRUE, NA),
prob = c(0.8, 0.2),
size = length(m),
replace = TRUE
)]))
# set up UI that allows user to pick x and y variables, see a plot,
# brush the plot, and see a table based on the brush
ui <- fluidPage(
titlePanel("Shiny Test"),
sidebarLayout(
sidebarPanel(
selectInput("xvar",
"pick x",
choices = names(mtnew)),
selectInput("yvar",
"pick y",
choices = names(mtnew))),
mainPanel(
plotOutput("myplot",
brush = brushOpts(id = "plot_brush")),
tableOutput("mytable")
)
)
)
server <- function(input, output) {
output$myplot <- renderPlot({
ggplot(data = mtnew) +
geom_point(aes(x = !!rlang::sym(input$xvar),
y = !!rlang::sym(input$yvar)))
})
output$mytable <- renderTable({
brush_out <- brushedPoints(mtnew, input$plot_brush)
})
}
# Complete app with UI and server components
shinyApp(ui, server)
I guess that you'll have to establish which data you want to represent.
You may want to have only defined record without NAs, in that case I would suggest to use the complete.cases function. Yet this solution will highly reduce your data set (below I've applied to your code).
Another option is to preserve all your records but without the NAs. In that case you should consider using imputation methods to set proper values in replacement. Take a look at this post which provides an example.
library(shiny)
library(tidyverse)
# replace some random values in mtcars with NA
set.seed(1)
mtnew <-
as.data.frame(lapply(mtcars, function(m)
m[sample(
c(TRUE, NA),
prob = c(0.8, 0.2),
size = length(m),
replace = TRUE
)]))
mtnew_complete <- mtnew[complete.cases(mtnew),]
# set up UI that allows user to pick x and y variables, see a plot,
# brush the plot, and see a table based on the brush
ui <- fluidPage(
titlePanel("Shiny Test"),
sidebarLayout(
sidebarPanel(
selectInput("xvar",
"pick x",
choices = names(mtnew)),
selectInput("yvar",
"pick y",
choices = names(mtnew))),
mainPanel(
plotOutput("myplot",
brush = brushOpts(id = "plot_brush")),
tableOutput("mytable")
)
)
)
server <- function(input, output) {
output$myplot <- renderPlot({
#ggplot(data = mtnew) +
ggplot(data = mtnew_complete) +
geom_point(aes(x = !!rlang::sym(input$xvar),
y = !!rlang::sym(input$yvar)))
})
output$mytable <- renderTable({
#brush_out <- brushedPoints(mtnew, input$plot_brush)
brush_out <- brushedPoints(mtnew_complete, input$plot_brush)
})
}
# Complete app with UI and server components
shinyApp(ui, server)
I am building an RShiny-app where I am creating a plot based on a data table which I can edit and another data table which I cannot. I eventually want to save all data points on the plot in a data table which I can display and export.
I have seen many ways to do this using ggplot (ie layer_data, ggplot_build), but no efficient ways when just using plot and lines. My plots will be getting quite complicated so it would be really helpful to find an easy way to do this rather than hardcoding everything in.
A very simple example of my code is below (Note: plots will be getting much more complicated than this. They will be line graphs, but I will just need the y values at each x value marked with a number on the x axis):
x <- data.frame('col_1' = c(1,2,3,4,5), 'col_2' = c(4,5,6,7,8))
y <- data.frame('col_1' = c(5,4,3,6,7), 'col_2' = c(1,2,3,4,5))
#import necessary libraries
library(shiny)
library(DT)
library(shinythemes)
library(rhandsontable)
#ui
ui <- fluidPage(theme = shinytheme("flatly"),
titlePanel("Test"),
sidebarLayout(
sidebarPanel(
#display data
rHandsontableOutput('contents'),
#update plot button
actionButton("go", "Plot Update"),
width=4
),
mainPanel(
tabsetPanel(
#plot
tabPanel("Plot", plotOutput("plot_1")) )
))
)
#server
server <- function(input, output, session) {
#data table
output$table_b <- renderTable(x)
indat <- reactiveValues(data=y)
observe({
if(!is.null(input$contents))
indat$data <- hot_to_r(input$contents)
})
output$contents <- renderRHandsontable({
rhandsontable(indat$data)
})
#save updated data
test <- eventReactive(input$go, {
live_data = hot_to_r(input$contents)
return(live_data)
})
#plot
output$plot_1 <- renderPlot({
plot(x[,1],x[,2],col='red',type = 'l')
lines(test()[,1],x[,2], col='black', type='l')
# need a way to grab data from plot a create a table
})
}
shinyApp(ui, server)
Given the following ui.R and server.R and circuit.csv; I can produce a simple plot which reacts to the user input (power in this case).
However, not all values for power are returned. For example, .5 produces a plot whereas .6 does not, so on and so forth at random occurrence throughout the power range.
If i plot as a table instead, to check my work, same thing, certain power inputs work as expected and others produce no table, and also no plot when asking to plot.
ui.R
library(shiny)
library(ggplot2)
shinyUI(fluidPage(
hr(),
sidebarLayout(
sidebarPanel(
sliderInput("power",label = "Power",
min = 0, max = 5, value = .5, step = .1)
),
mainPanel(
p("Lum vs Distance by Power"),
plotOutput('plot1')
)
)
))
server.R
library(shiny)
library(ggplot2)
df <- read.table(file = "circuit.csv", sep=",", header = TRUE)
shinyServer(function(input, output) {
output$plot1 <- renderPlot({
df2 <- subset(df,df$pow==input$power)
p <- ggplot(df2)+
geom_point(aes(x=dist, y=lum))
print(p)
})
})
Link to github (for csv data)
I would post images but am not allowed to do so at this time.