In the following shiny app, I have embedded the annual and monthly functions on line 7-15 into the selectizeInput placeholder on line 22.
library(shiny)
library(shinydashboard)
library(tidyquant)
library(tidyverse)
library(plotly)
annual <- function(x){
(x/lag(x, 12) - 1)*100
}
monthly <- function(x){
(x/lag(x) - 1)*100
}
ui <- dashboardPage(
dashboardHeader(title = 'Dashboard'),
dashboardSidebar(),
dashboardBody(
fluidRow(
box(selectizeInput('select_calculation', 'Calculation',
choices = c('Monthly' = monthly, 'Annual' = annual)
), height=80,width=4,
)
),
fluidRow(
box(plotlyOutput("chart"))
)
)
)
server <- function(input, output) {
output$chart <- renderPlotly({
chart <- tidyquant::tq_get('PCE',
from = '2019-01-01',
to = '2022-10-01',
get = 'economic.data') %>%
select(-symbol) %>%
mutate_if(is.numeric, ~input$select_calculation(.)) %>%
drop_na() %>% {
ggplot(., aes(x = date, y = price)) +
geom_line()
} %>%
ggplotly()
})
}
shinyApp(ui, server)
When I call one of the formulas in the code for my chart (e.g ~annual(.) on line 44, my app works fine.
However when I try to run this interactively using the selectizeInput option by amending line 44 as follows
mutate_if(is.numeric, ~input$select_calculation(.)) %>%
I get the following error. Is there any way to call a function interactively successfully?
I already wondered where you want to go with this. The issue is that input$select_calculation is a character not a function, i.e. to make your code work you have to parse the input using e.g.
output$chart <- renderPlotly({
calc_method <- eval(parse(text = input$select_calculation))
chart <- tidyquant::tq_get("PCE",
from = "2019-01-01",
to = "2022-10-01",
get = "economic.data"
) %>%
select(-symbol) %>%
mutate_if(is.numeric, ~ calc_method(.)) %>%
drop_na() %>%
{
ggplot(., aes(x = date, y = price)) +
geom_line()
} %>%
ggplotly()
})
But IMHO the easier approach would be to use e.g. switch inside the server to switch the function used for the calculations instead of trying to pass the function via choices:
library(shiny)
library(shinydashboard)
library(tidyquant)
library(tidyverse)
library(plotly)
annual <- function(x) {
(x / lag(x, 12) - 1) * 100
}
monthly <- function(x) {
(x / lag(x) - 1) * 100
}
ui <- dashboardPage(
dashboardHeader(title = "Dashboard"),
dashboardSidebar(),
dashboardBody(
fluidRow(
box(selectizeInput("select_calculation", "Calculation",
choices = c("Monthly" = "monthly", "Annual" = "annual")
), height = 80, width = 4, )
),
fluidRow(
box(plotlyOutput("chart"))
)
)
)
server <- function(input, output) {
output$chart <- renderPlotly({
calc_method <- switch(input$select_calculation,
"monthly" = monthly,
"annual" = annual
)
chart <- tidyquant::tq_get("PCE",
from = "2019-01-01",
to = "2022-10-01",
get = "economic.data"
) %>%
select(-symbol) %>%
mutate_if(is.numeric, ~ calc_method(.)) %>%
drop_na() %>%
{
ggplot(., aes(x = date, y = price)) +
geom_line()
} %>%
ggplotly()
})
}
shinyApp(ui, server)
#>
#> Listening on http://127.0.0.1:6727
Related
I need to control the number of chart using a slideInput.
I have a list with ggplot charts. Once my slider came from 1 to 2 it will display the first 2 charts of this list. If the slider range is from 1:3 it will display the first 3 charts from this list chart.
This is what Ive done so far:
library(shiny)
library(gapminder)
library(highcharter)
df <- gapminder %>% group_split(country)
countries <- df[1:10] %>% set_names(1:10)
ggplots_list <- countries %>% map(~ .x %>% ggplot(aes(x = year, y = pop)) + geom_line())
library(shiny)
ui <- fluidPage(
sliderInput(inputId = "slider_new",
label = "Projections Range",
width = '100%',
min = 1, max = 10,
value = 1
) ,
plotOutput('chart_1', height = '500px')
)
server <- function(input, output, session) {
output$chart_1 <- renderPlot({
ggplots_list[input$slider_new[1]]
})
}
shinyApp(ui, server)
The idea is to have a grid of charts as I increase the slider value.
Any help?
Try this
library(gapminder)
library(highcharter)
library(purrr)
df <- gapminder %>% group_split(country)
countries <- df[1:10] %>% set_names(1:10)
ggplots_list <- countries %>% map(~ .x %>% ggplot(aes(x = year, y = pop)) + geom_line())
library(shiny)
ui <- fluidPage(
sliderInput(inputId = "slider_new",
label = "Projections Range",
width = '100%',
min = 1, max = 10,
value = 1
) ,
uiOutput("chart_1")
)
server <- function(input, output, session) {
lapply(1:10, function(i){
output[[paste0("plots",i)]] <- renderPlot({ ggplots_list[i] })
})
output$chart_1 <- renderUI({
n <- input$slider_new
lapply(1:n, function(i) plotOutput(paste0("plots",i), height=500))
})
}
shinyApp(ui, server)
I am new to the shiny app and trying to write simple code.
I changed the codes so many times but my bar chart doesn't work.
I have this problem in my other trying. That the UI works and also the codes in the server work part by part in R but not in the shiny app. I know some part of my server is not what I want, I just want to know what should I do to run the code which works in R but not in Shiny
#Graph 2
server<-#Graph 2
library("tidyverse")
library("leaflet")
library("leaflet.extras")
library("rnaturalearthdata")
library("sf")
library("DT")
library("ggplot2")
N <- read.csv("https://data.ontario.ca/dataset/f4112442-bdc8-45d2-be3c-12efae72fb27/resource/455fd63b-603d-4608-8216-7d8647f43350/download/conposcovidloc.csv")
function(input, output, session){
if(input$data.Gender){
City ="Ottawa"
N %>% subset(Reporting_PHU_City == City) %>%
select(Case_Reported_Date, Age_Group, Client_Gender, Outcome1)%>%
rename(Date = Case_Reported_Date)%>%
arrange(Age_Group, Client_Gender, Outcome1)
Data.N <- as.data.frame(N)
Data.N %>%
group_by(Age_Group) %>%
summarise(Age = n_distinct(Age_Group)) %>%
arrange(desc(Age))
w = table(N$Age_Group)
t = as.data.frame(w)
}
output$Plot <- renderPlot({
ggplot() +
geom_bar(stat = "identity",data = t,mapping = aes(x = N$Client_Gender , y =Freq))
})
}
Sorry, the site didn't let me share the UI too. This is Ui
UI<- #Graph 2
library("leaflet")
library("DT")
fluidPage(
sidebarLayout(
sidebarPanel(
radioButtons("data.Gender", "",
c("Data female" = "Gender.Female",
"Data male" = "Gender.Male"))
),
enter code here
mainPanel(
plotOutput("Plot")
)
))
Perhaps you should group by Client_Gender. Your present group by of Age_Group will give 1 as the value for all groups.
Try this
server <- function(input, output, session){
t <- reactive({
input$data.Gender
City ="Toronto"
aa <- N %>% subset(Reporting_PHU_City == City) %>%
select(Case_Reported_Date, Age_Group, Client_Gender, Outcome1)%>%
rename(Date = Case_Reported_Date)%>%
arrange(Age_Group, Client_Gender, Outcome1)
bb <- aa %>%
group_by(Client_Gender) %>%
summarise(Age = n_distinct(Age_Group)) %>%
arrange(desc(Age))
bb
})
output$Plot <- renderPlot({
ggplot(data=t()) +
geom_bar(stat = "identity",mapping = aes(x = Client_Gender , y = Age))
})
}
I am trying to get a slider within my barplot page to make the data interactive per year.
#library
library(dplyr)
library(shiny)
library(shinythemes)
library(ggplot2)
#Source
dataset <- read.csv("Wagegap.csv")
SFWage <- dataset %>%
group_by(gender,JobTitle, Year) %>%
summarise(averageBasePay = mean(BasePay, na.rm=TRUE)) %>%
select(gender, JobTitle, averageBasePay, Year)
clean <- SFWage %>% filter(gender != "")
#UI
ui <- fluidPage(
theme = shinytheme("united"),
navbarPage("San Fransisco Wages",
tabPanel("Barplot",
mainPanel(
plotOutput("barplot")
)) ,
tabPanel("Table",
mainPanel(
dataTableOutput("table")
))
)
)
#server
server <- function(input, output){
output$barplot <- renderPlot({
ggplot(clean, aes(x = JobTitle, y = averageBasePay ))+
geom_bar(stat="Identity", width = 0.3, fill="orange")+
labs(x= "Jobs", y = "Wage", title = "Wage per job")
})
output$table <- renderDataTable({
clean
})
}
#Run App
shinyApp(ui = ui, server = server)
I don't fully understand it yet how to put this input in.
I have tried sliding it into the navbarpage but I can't figure out how it works.
I also tried making year reactive but with no success.
It's not the year that has to be reactive; it's the whole data frame. Therefore, in your ui, you can do:
[...]
tabPanel("Barplot",
mainPanel(
sliderInput("year", label = "Which year should be displayed?", min = 1900, max = 2020, step = 5, value = 2000) # new
plotOutput("barplot")
)) ,
[...]
I put it there for convenience; the layout is yours. I tried do change as little as possible.
The server would then have:
server <- function(input, output){
# NEW ########################################
clean <- reactive({
SFWage <- dataset %>%
group_by(gender,JobTitle, Year) %>%
summarise(averageBasePay = mean(as.numeric(BasePay), na.rm=TRUE)) %>% # Notice the as.numeric()
select(gender, JobTitle, averageBasePay, Year)
SFWage %>% filter(gender != "" & Year == input$year)
})
# OLD ########################################
output$barplot <- renderPlot({
ggplot(clean(), aes(x = JobTitle, y = averageBasePay ))+ # Parenthesis
geom_bar(stat="Identity", width = 0.3, fill="orange")+
labs(x= "Jobs", y = "Wage", title = "Wage per job")
})
output$table <- renderDataTable({
clean() # Parenthesis
})
}
Don't forget to add the parenthesis, as I did here.
This should work, but I might have mistyped something or got it completely wrong. Since I don't have your data, I can't test it.
EDIT: Due to your comment, I added the as.numeric() term, as you can see above. However, if your data is not only not numeric but also with ,, you can do:
[...]
summarise(averageBasePay = mean(as.numeric(gsub(",", ".", BasePay)), na.rm=TRUE)) %>% # Notice the as.numeric() and the gsub()
[...]
I am new to Shiny and, as an exercise, I am trying to assess global trends over time using the Gapminder data set. My aim is to produce a basic app that allows me to plot life expectancy (lifeExp), population (pop) and GDP per capita (gdpPercap) over time (year) separately. However, when I enter the following code all I get is a ggplot with a straight line. What am I missing?
Thanks in advance!
library(shiny)
library(gapminder)
library(dplyr)
library(ggplot2)
ui <- fluidPage(
selectInput(inputId = "variables",
label = "Select Variable",
choices = names(gapminder[, 4:6])),
plotOutput("plot")
)
server <- function(input, output){
output$plot <- renderPlot({
data <- gapminder %>% group_by(year) %>%
summarise(lifeExp = mean(lifeExp, na.rm = T),
pop = mean(pop, na.rm = T),
gdpPercap = mean(gdpPercap, na.rm = T))
ggplot(data, aes(x = year, y = input$variables)) + geom_line()
})
}
shinyApp(ui = ui, server = server)
With modern versions of ggplot2 rlang, we may modify the aes call to aes(x = year, y = .data[[input$variables]])) and do:
library(shiny)
library(gapminder)
library(dplyr)
library(ggplot2)
ui <- fluidPage(
selectInput(inputId = "variables",
label = "Select Variable",
choices = names(gapminder[, 4:6])),
plotOutput("plot")
)
server <- function(input, output){
output$plot <- renderPlot({
data <- gapminder %>% group_by(year) %>%
summarise(lifeExp = mean(lifeExp, na.rm = TRUE),
pop = mean(pop, na.rm = TRUE),
gdpPercap = mean(gdpPercap, na.rm = TRUE))
ggplot(data, aes(x = year, y = .data[[input$variables]])) +
geom_line()
})
}
shinyApp(ui = ui, server = server)
Reference: https://ggplot2.tidyverse.org/dev/articles/ggplot2-in-packages.html#using-aes-and-vars-in-a-package-function
Using R Shiny and plotly I created a interactive scatter plot.
How can I modify my code to interactively label only the points which were selected by the user?
Example plot
Thank you so much for your help!
All the best,
Christian
library(plotly)
library(shiny)
library(dplyr)
data <- data.frame(matrix(runif(500,0,1000), ncol = 2, nrow = 100)) %>%
mutate(ID = row_number())
ui <- fluidPage(
plotlyOutput("plot"),
verbatimTextOutput("hover"),
verbatimTextOutput("click"),
verbatimTextOutput("brush"),
verbatimTextOutput("zoom"))
server <- function(input, output, session) {
output$plot <- renderPlotly({
p <- ggplot(data, aes(x = X1, y = X2, key = ID)) +
geom_point()
ggplotly(p) %>% layout(dragmode = "select")
})
}
shinyApp(ui, server)
Below is a possible solution. I use a reactive function to "label" selected points. I wasn't sure how exactly you want to display the IDs for selected points. The code adds the ID as text when a point is selected. Also, I add some jitter to move the IDs away from the points.
library(plotly)
library(shiny)
library(dplyr)
data <- data.frame(matrix(runif(500,0,1000), ncol = 2, nrow = 100)) %>%
mutate(ID = row_number())
ui <- fluidPage(
plotlyOutput("plot"),
verbatimTextOutput("hover"),
verbatimTextOutput("click"),
verbatimTextOutput("brush"),
verbatimTextOutput("zoom"))
server <- function(input, output, session) {
output$plot <- renderPlotly({
data <- get_data()
p <- ggplot(data, aes(x = X1, y = X2, key = ID)) +
geom_point() + geom_text(data=subset(data, show_id),aes(X1,X2,label=ID), position = position_jitter(width = 20,height = 20))
ggplotly(p, source = "subset") %>% layout(dragmode = "select")
})
get_data <- reactive({
event.data <- event_data("plotly_selected", source = "subset")
data <- data %>% mutate(show_id = FALSE)
if (!is.null(event.data)) {
data$show_id[event.data$pointNumber + 1] <- TRUE
}
data
})
}
shinyApp(ui, server)