I am trying to add vlines to a density plot in shiny for R. For reproducible purposes, I will use the iris data set. The data is clustered using kmeans from the cluster package. Outliers are located by measuring distances from the centers of clusters. Then I wish to create a density plot that has vlines and labels for each of the outliers.
The code works outside of shiny. Inside my shiny app, I get an error message: Error in [: invalid subscript type 'list'. I have tried unlist and making the outliers a variety of other forms and still get the list error. How do I add the vlines?
Global
library(tidyverse)
library(cluster)
library(shiny)
require(iris)
UI
ui <- fluidPage({
pageWithSidebar(
headerPanel('Iris k-means clustering'),
sidebarPanel(
numericInput('clusters', 'Cluster count', 3, min = 1, max = 9)
),
mainPanel(
plotOutput('plot1')
)
)
})
Server
server <- function(input, output){
ClusterData <- reactive({
iris[,1:4]
})
# need to keep row numbers for outlier labels
ClusterData2 <- reactive({
ClusterData2 <- data.frame(ClusterData())
row.names(ClusterData2) <- 1:nrow(ClusterData2)
return(ClusterData2)
})
# scale the iris data
ScaledData <- reactive({
scale(ClusterData2())
})
# kmeans clustering
final <- reactive({
kmeans(ScaledData(), 3, nstart = 25)
})
# find centers
states.centers <- reactive({
final()$centers[final()$cluster, ]
})
# find outliers
distances <- reactive({
sqrt(rowSums((ScaledData() - states.centers())^2))
})
# bind distances back to data
outliers <- reactive({
cbind(ClusterData(), Distance = distances())
})
# bind cluster number to data
clusterMember <- reactive({
cbind(outliers(), clusterNum = final()$cluster)
})
# turn into data frame
clusterMember2 <- reactive({
as.data.frame(clusterMember())
})
# find points that are their own cluster
dist0 <- reactive({
clusterMember() %>%
filter(distances() == 0)
})
# arrange distances largest to smallest
distArrange <- reactive({
clusterMember() %>%
arrange(desc(Distance))
})
# find top 5 outliers
filtTop5 <- reactive({
distArrange()[1:5,]
})
# bind outliers and single clusters together
AllOutliers <- reactive({
rbind(filtTop5(), dist0())
})
# for density plot: vlines and labels
lines_amt <- reactive({
data.frame(vlines = (clusterMember2()$Petal.Length[c(AllOutliers())]), labels = c(AllOutliers()))
})
########## output
output$plot1 <- renderPlot({
ClusterData() %>%
ggplot(aes(x = Petal.Length)) +
geom_density(fill = "blue", alpha = 0.4) #+
geom_vline(data = lines_amt(), aes(xintercept = get(vlines)))
})
}
Run App
shinyApp(ui, server)
Thank you.
The plot should look like the link.
PetalLengthDensityPlot
I think I have it all sorted out. Essentially I removed your lines_amt() reactive, and replaced geom_vline(), while also adding an annotate() for the labels:
library(tidyverse)
library(cluster)
library(shiny)
ui <- fluidPage({
pageWithSidebar(
headerPanel('Iris k-means clustering'),
sidebarPanel(
numericInput('clusters', 'Cluster count', 3, min = 1, max = 9)
),
mainPanel(
plotOutput('plot1')
)
)
})
server <- function(input, output){
ClusterData <- reactive({
iris[,1:4]
})
# need to keep row numbers for outlier labels
ClusterData2 <- reactive({
ClusterData2 <- data.frame(ClusterData())
row.names(ClusterData2) <- 1:nrow(ClusterData2)
return(ClusterData2)
})
# scale the iris data
ScaledData <- reactive({
scale(ClusterData2())
})
# kmeans clustering
final <- reactive({
kmeans(ScaledData(), 3, nstart = 25)
})
# find centers
states.centers <- reactive({
final()$centers[final()$cluster, ]
})
# find outliers
distances <- reactive({
sqrt(rowSums((ScaledData() - states.centers())^2))
})
# bind distances back to data
outliers <- reactive({
cbind(ClusterData(), Distance = distances())
})
# bind cluster number to data
clusterMember <- reactive({
cbind(outliers(), clusterNum = final()$cluster)
})
# turn into data frame
clusterMember2 <- reactive({
as.data.frame(clusterMember())
})
# find points that are their own cluster
dist0 <- reactive({
clusterMember() %>%
filter(distances() == 0)
})
# arrange distances largest to smallest
distArrange <- reactive({
clusterMember() %>%
arrange(desc(Distance))
})
# find top 5 outliers
filtTop5 <- reactive({
distArrange()[1:5,]
})
# bind outliers and single clusters together
AllOutliers <- reactive({
rbind(filtTop5(), dist0())
})
# for density plot: vlines and labels #Made the lines and labels without this
# lines_amt <- reactive({
# data.frame(vlines = (clusterMember2()$Petal.Length[c(AllOutliers()$Petal.Length)]), labels = c(AllOutliers()))
# })
########## output
output$plot1 <- renderPlot({
ClusterData() %>%
ggplot(aes(x = Petal.Length)) +
geom_density(fill = "blue", alpha = 0.4) +
# geom_vline(xintercept = lines_amt()$vlines)
geom_vline(xintercept = AllOutliers()$Petal.Length)+ #Used this in place of your current geom_vline()
annotate("text", x = AllOutliers()$Petal.Length, #Added this to add the text
y = 0,
label = rownames(AllOutliers()),
hjust = -1,
vjust = -1)
# geom_vline(data = lines_amt(), aes(xintercept = get(vlines)))
})
}
shinyApp(ui, server)
Hopefully this helps!
Related
I have the following App:
The objective is to:
Add new points to the plot when the user clicks on it.
These are updated in the table (where you can remove points also)
(Where the App fails): Plot the linear regression and spline regression based on the new users updated data.
When I comment-out the lines
#geom_line(aes(x=x, y=fitlm(), color="Simple")) +
#geom_line(aes(x=x, y=fitbslm(), color="B-spline")) +
in the ggplot renderPlot() function at the end, I am able to add points and update the plot without problem
The problem occurs when I try to add these two lines back into the plot and then the updated data is passed to the fitlm and fitBslm eventReactive() functions.
For some reason it doesn't want to re-compute the regressions and apply/update the plot.
Question:
How can I introduce the regressions to the ggplot based on the new users updated data. (I am happy with it updating automatically or through a button)
After clicking the Generate Plot button it makes the below plot. However, the plot failed Error: [object Object] when I click on the plot to add a new point.
App:
library(shiny)
library(dplyr)
library(splines2)
library(ggplot2)
# Get the Temp values, which defines the accepted range of knots
# for the b-spline model.
library(dplyr)
data("airquality")
airquality <- filter(airquality, !is.na(Ozone)) %>%
select(c(Ozone, Temp)) %>%
set_names(c("x", "y"))
uniqueTemps <- unique(airquality[order(airquality$x), "x"])
selectedTemps <- sample(uniqueTemps, 2)
# Define UI for application that draws a histogram
ui <- shinyUI(fluidPage(
# Application title
titlePanel("Simple Linear vs Spline Fit"),
# Sidebar
sidebarLayout(
sidebarPanel(
selectInput("knotSel", "Select knot values for B-spline fit:",
uniqueTemps, selected=selectedTemps,
multiple=TRUE),
actionButton("calcFit", "Generate Plot"),
actionButton("computeRegressions", "Compute Regressions")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("plot_splines", click = "plot_click"),
h4("Example Data: airquality {datasets}"),
p("This plot uses linear models to predict ozone levels based on temperature readings.",
tags$br(),
tags$em("Simple formula: ")
# tags$code("lm(Ozone ~ Temp + I(Temp^2) + I(Temp^3) - 1, airquality)"),
# tags$br(),
# tags$em("Spline formula: "),
# tags$code("lm(airquality$Ozone ~ bSpline(airquality$Temp, knots=getKnots(), degree=3) - 1)")
),
fluidRow(column(width = 6,
h4("Click plot to add points"),
actionButton("rem_point", "Remove Last Point")
#plotOutput("plot1", click = "plot_click")
),
column(width = 6,
h4("Table of points on plot"),
tableOutput("table"))),
fluidRow(column(width = 6,
DTOutput('tab1')),
column(width = 6,
DTOutput('tab2'))
)
)
)))
server <- (function(input, output) {
# Load the airquality dataset.
# data("airquality")
# # Remove observations lacking an Ozone measure.
# airquality <- filter(airquality, !is.na(Ozone)) %>%
# select(c(Ozone, Temp)) %>%
# set_names(c("y", "x"))
########################### Add selections to plot ###########################
## 1. set up reactive dataframe ##
values <- reactiveValues()
values$DT <- data.frame(x = numeric(),
y = numeric()
) %>%
bind_rows(airquality)
## 2. Create a plot ##
# output$plot1 = renderPlot({
# ggplot(values$DT, aes(x = x, y = y)) +
# geom_point(size = 5) +
# lims(x = c(0, 100), y = c(0, 100)) +
# theme(legend.position = "bottom")
# # include so that colors don't change as more color/shape chosen
# # scale_color_discrete(drop = FALSE) +
# # scale_shape_discrete(drop = FALSE)
# })
## 3. add new row to reactive dataframe upon clicking plot ##
observeEvent(input$plot_click, {
# each input is a factor so levels are consistent for plotting characteristics
add_row <- data.frame(x = input$plot_click$x,
y = input$plot_click$y
)
# add row to the data.frame
values$DT <- rbind(values$DT, add_row)
})
## 4. remove row on actionButton click ##
observeEvent(input$rem_point, {
rem_row <- values$DT[-nrow(values$DT), ]
values$DT <- rem_row
})
## 5. render a table of the growing dataframe ##
output$table <- renderTable({
values$DT
})
##############################################################################
# Fit the simple linear model
fitlm <- eventReactive(input$calcFit, {
slm <- lm(y ~ x + I(x^2) + I(x^3) - 1, values$DT)
fitlm <- slm$fitted.values
fitlm
})
# Get knot selection
getKnots <- reactive({as.integer(input$knotSel)})
# Fit the spline model, with the knot selection
fitBslm <- eventReactive(input$calcFit, {
bsMat <- bSpline(values$DT$x, knots=getKnots(), degree=3)
bslm <- lm(values$DT$y ~ bsMat - 1)
bslm
})
# observeEvent({
# print(fitBslm())
# })
# Generate the plot
output$plot_splines <- renderPlot({
splineMdl <- fitBslm()
fitbslm <- splineMdl$fitted.values
cols <- c("Simple"="#ef615c", "B-spline"="#20b2aa", "knot"="black")
g <- ggplot(values$DT, aes(x=x, y=y)) +
geom_point(color="blue") +
geom_line(aes(x=x, y=fitlm(), color="Simple")) +
#geom_line(aes(x=x, y=fitbslm(), color="B-spline")) +
geom_vline(aes(color="knot"), xintercept=getKnots(), linetype="dashed", size=1) +
scale_colour_manual(name="Fit Lines",values=cols) +
ggtitle("Ozone as predicted by Temp", "(knots shown as vertical lines)")
g
})
output$tab1 <- renderDataTable(
airquality
)
output$tab2 <- renderDataTable(
values$DT
)
})
shinyApp(ui, server)
Change eventReactive to just reactive. Also, you just need fitbslm in the second geom_line without (). Try this
server <- (function(input, output) {
########################### Add selections to plot ###########################
## 1. set up reactive dataframe ##
values <- reactiveValues()
values$DT <- data.frame(x = numeric(),
y = numeric()
) %>%
bind_rows(airquality)
## 3. add new row to reactive dataframe upon clicking plot ##
observeEvent(input$plot_click, {
# each input is a factor so levels are consistent for plotting characteristics
add_row <- data.frame(x = input$plot_click$x,
y = input$plot_click$y
)
# add row to the data.frame
values$DT <- rbind(values$DT, add_row)
})
## 4. remove row on actionButton click ##
observeEvent(input$rem_point, {
rem_row <- values$DT[-nrow(values$DT), ]
values$DT <- rem_row
})
## 5. render a table of the growing dataframe ##
output$table <- renderTable({
values$DT
})
##############################################################################
# Fit the simple linear model
# fitlm <- eventReactive(input$calcFit, {
fitlm <- reactive({
slm <- lm(y ~ x + I(x^2) + I(x^3) - 1, values$DT)
fitlm <- slm$fitted.values
fitlm
})
# Get knot selection
getKnots <- reactive({as.integer(input$knotSel)})
# Fit the spline model, with the knot selection
#fitBslm <- eventReactive(input$calcFit, {
fitBslm <- reactive({
bsMat <- bSpline(values$DT$x, knots=getKnots(), degree=3)
bslm <- lm(values$DT$y ~ bsMat - 1)
bslm
})
myPlot <- reactive({
splineMdl <- fitBslm()
fitbslm <- splineMdl$fitted.values
cols <- c("Simple"="#ef615c", "B-spline"="#20b2aa", "knot"="black")
g <- ggplot(values$DT, aes(x=x, y=y)) +
geom_point(color="blue") +
geom_line(aes(x=x, y=fitlm(), color="Simple")) +
geom_line(aes(x=x, y=fitbslm , color="B-spline")) +
geom_vline(aes(color="knot"), xintercept=getKnots(), linetype="dashed", size=1) +
scale_colour_manual(name="Fit Lines",values=cols) +
ggtitle("Ozone as predicted by Temp", "(knots shown as vertical lines)")
g
})
# Generate the plot
output$plot_splines <- renderPlot({
myPlot()
})
output$tab1 <- renderDataTable(
airquality
)
output$tab2 <- renderDataTable(
values$DT
)
})
I would like to be able to zoom in on the vlines in a density plot in shiny. I am using the iris dataset for reproducible purposes. The vlines are labeled with row names.
In my actual dataset, I have many vlines very close to each other. They are so close that I often cannot distinguish the row number labels. I would like to find a way to zoom in on the vline labels. I have attempted using a brush but that is not working.
library(tidyverse)
library(cluster)
library(shiny)
ui <- fluidPage({
pageWithSidebar(
headerPanel('Iris k-means clustering'),
sidebarPanel(
numericInput('clusters', 'Cluster count', 3, min = 1, max = 9)
),
mainPanel(
plotOutput('plot1',
dblclick = 'plot1_dblclick',
brush = brushOpts(
id = 'plot1_brush',
resetOnNew = TRUE
))
)
)
})
server <- function(input, output){
ClusterData <- reactive({
iris[,1:4]
})
# need to keep row numbers for outlier labels
ClusterData2 <- reactive({
ClusterData2 <- data.frame(ClusterData())
row.names(ClusterData2) <- 1:nrow(ClusterData2)
return(ClusterData2)
})
# scale the iris data
ScaledData <- reactive({
scale(ClusterData2())
})
# kmeans clustering
final <- reactive({
kmeans(ScaledData(), input$clusters, nstart = 25)
})
# find centers
states.centers <- reactive({
final()$centers[final()$cluster, ]
})
# find outliers
distances <- reactive({
sqrt(rowSums((ScaledData() - states.centers())^2))
})
# bind distances back to data
outliers <- reactive({
cbind(ClusterData(), Distance = distances())
})
# bind cluster number to data
clusterMember <- reactive({
cbind(outliers(), clusterNum = final()$cluster)
})
# turn into data frame
clusterMember2 <- reactive({
as.data.frame(clusterMember())
})
# find points that are their own cluster
dist0 <- reactive({
clusterMember() %>%
filter(distances() == 0)
})
# arrange distances largest to smallest
distArrange <- reactive({
clusterMember() %>%
arrange(desc(Distance))
})
# find top 5 outliers
filtTop5 <- reactive({
distArrange()[1:5,]
})
# bind outliers and single clusters together
AllOutliers <- reactive({
rbind(filtTop5(), dist0())
})
########## output plot
output$plot1 <- renderPlot({
ClusterData() %>%
ggplot(aes(x = Petal.Length)) +
geom_density(fill = "blue", alpha = 0.4) +
geom_vline(xintercept = AllOutliers()$Petal.Length) +
annotate("text", x = AllOutliers()$Petal.Length,
y = 0,
label = rownames(AllOutliers()),
hjust = 0.5,
vjust = -1)
})
######### zoom brush
observeEvent(input$plot1_dblclick, {
brush <- input$plot1_brush
if (!is.null(brush)) {
ranges$x <- c(brush$xmin, brush$xmax)
ranges$y <- c(brush$ymin, brush$ymax)
} else {
ranges$x <- NULL
ranges$y <- NULL
}
})
}
shinyApp(ui, server)
I am not invested in the above approach. Any suggestions would be welcome.
Thank you.
I advise you to try plotly package.
Modified code from your question:
library(tidyverse)
library(cluster)
library(shiny)
library(plotly)
ui <- fluidPage({
pageWithSidebar(
headerPanel('Iris k-means clustering'),
sidebarPanel(
numericInput('clusters', 'Cluster count', 3, min = 1, max = 9)
),
mainPanel(
plotlyOutput('plot1')
)
)
})
server <- function(input, output){
ClusterData <- reactive({
iris[,1:4]
})
# need to keep row numbers for outlier labels
ClusterData2 <- reactive({
ClusterData2 <- data.frame(ClusterData())
row.names(ClusterData2) <- 1:nrow(ClusterData2)
return(ClusterData2)
})
# scale the iris data
ScaledData <- reactive({
scale(ClusterData2())
})
# kmeans clustering
final <- reactive({
kmeans(ScaledData(), input$clusters, nstart = 25)
})
# find centers
states.centers <- reactive({
final()$centers[final()$cluster, ]
})
# find outliers
distances <- reactive({
sqrt(rowSums((ScaledData() - states.centers())^2))
})
# bind distances back to data
outliers <- reactive({
cbind(ClusterData(), Distance = distances())
})
# bind cluster number to data
clusterMember <- reactive({
cbind(outliers(), clusterNum = final()$cluster)
})
# turn into data frame
clusterMember2 <- reactive({
as.data.frame(clusterMember())
})
# find points that are their own cluster
dist0 <- reactive({
clusterMember() %>%
filter(distances() == 0)
})
# arrange distances largest to smallest
distArrange <- reactive({
clusterMember() %>%
arrange(desc(Distance))
})
# find top 5 outliers
filtTop5 <- reactive({
distArrange()[1:5,]
})
# bind outliers and single clusters together
AllOutliers <- reactive({
rbind(filtTop5(), dist0())
})
########## output plot
output$plot1 <- renderPlotly({
plot1 <- ClusterData() %>%
ggplot(aes(x = Petal.Length)) +
geom_density(fill = "#6495ed", alpha = 0.3) +
geom_vline(xintercept = AllOutliers()$Petal.Length, size = 0.5, colour = "#013220") +
annotate("text", x = AllOutliers()$Petal.Length,
y = 0,
label = rownames(AllOutliers()),
colour = "#d4240b",
size = 4)
ggplotly(plot1)
})
}
shinyApp(ui, server)
Output (zoomed with cluster count = 9):
I have a question about the checkboxInput in R shiny. When it is checked, the scatter plot should be colorful while when it is unchecked, the plot should be black. I have tried several methods, but it keeps colorful no matter whether it is checked or not. Could you please help me with fix the code? Thanks so much.
library(shiny)
library(dplyr)
library(ggplot2)
# Start a 'Shiny' part
shinyServer(function(input, output, session) {
# Create a new reactive variable
newVar <- reactive({
newData <- msleep %>% filter(vore == input$vore)
})
# Create a scatter plot
output$sleepPlot <- renderPlot({
newDat <- newVar()
g <- ggplot(newDat, aes(x = bodywt, y = sleep_total))
g + geom_point(size = input$size, aes(col = conservation))
})
# Create text info
output$info <- renderText({
newDat <- newVar()
paste("The average body weight for order", input$vore, "is", round(mean(newDat$bodywt, na.rm = TRUE), 2),
"and the average total sleep time is", round(mean(newDat$sleep_total, na.rm = TRUE), 2), sep = " ")
})
# Create output of observations
output$table <- renderTable({
newDat <- newVar()
newDat
})
})
library(ggplot2)
shinyUI(fluidPage(
# Application title
titlePanel("Investigation of Mammal Sleep Data"),
# Sidebar with options for the data set
sidebarLayout(
sidebarPanel(
h3("Select the mammal's biological order:"),
selectizeInput("vore", "Vore", selected = "omni",
choices = levels(as.factor(msleep$vore))),
br(),
sliderInput("size", "Size of Points on Graph",
min = 1, max = 10, value = 5, step = 1),
checkboxInput("conservation", h4("Color Code Conservation Status", style = "color:red;"))
),
# Show output
mainPanel(
plotOutput("sleepPlot"),
textOutput("info"),
tableOutput("table")
)
)
))
Try this
# Create a scatter plot
output$sleepPlot <- renderPlot({
newDat <- newVar()
colorme <- unique(newVar()$conservation)
ncolor <- length(colorme)
if (!input$conservation) {
mycolor <- c(rep("black",ncolor))
mylabels <- c(rep(" ",ncolor))
}
g <- ggplot(newDat, aes(x = bodywt, y = sleep_total)) +
geom_point(size = input$size, aes(col = conservation)) +
{if (!input$conservation) scale_color_manual(name=" ", values=mycolor, labels=mylabels)} +
{ if (!input$conservation) guides(color='none')}
g
})
You can adjust, as necessary.
I have a problem. I want to use sidebar to curb time series plot, however, I get invalid formula error when trying to do the plot. Can someone pls help?
server.r
library(shiny)
library(BCA)
data(Eggs)
# Define server logic required to plot
shinyServer(function(input, output) {
formulaX <- reactive({
tmp <- paste(input$range,collapse = ":")
paste("Eggs[",tmp,",1]")
})
formulaY <- reactive({
tmp1 <- paste(input$range,collapse = ":")
paste("Eggs[",tmp1,",5]")
})
# Return the formula text for printing as a caption
output$caption <- renderText({
paste(formulaX(),formulaY(),sep = " ")
})
#creating plot -ERROR
output$mpgPlot <- renderPlot({
plot(as.formula(formulaX()),as.formula(formulaY()))
})
})
ui.r
library(shiny)
# Define UI
shinyUI(pageWithSidebar(
# Application title
headerPanel("Eggs"),
sidebarPanel(
# Specification of range within an interval
sliderInput("range", "Range:",
min = 1, max = 105, value = c(20,50))
),
mainPanel(
h3(textOutput("caption")),
plotOutput("mpgPlot")
)
))
"Eggs[1:10,1]" is not a formula, it is a character-representation of a subset. Since you are always choosing columns 1 and 5, your "formula" is always "Cases ~ Week" (I don't have BCA installed, I think that's correct), and you are intending to use a subset of rows from the data.
Perhaps this would work instead (hasty, some programming safeguards would be appropriate):
# no need for formulaX(), formulaY()
# not certain what you want/need from output$caption
dataX <- reactive({ Eggs[input$range[1]:input$range[2],,drop = FALSE] })
and your plot:
output$mpgPlot <- renderPlot({
plot(Cases ~ Week, data = dataX())
})
or
output$mpgPlot <- renderPlot({
x <- dataX()
plot(x$Week, x$Cases)
})
I built the shiny app below that updates the line graph based on the user's input. It works fine until I try to generate a 2nd output. How can I display the value total.weight calculated in the renderPlot() function? It seems to me my data set df and the variable total.weight should be created "outside" of the renderPlot() function but I have not figured out how.
ui.r
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Reproducible Example"),
# Sidebar with a slider input for the number of bins
sidebarLayout(
sidebarPanel(
selectInput("ID", "group", c("A", "B"))
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("plot1"),
verbatimTextOutput("text1")
)
)
))
server.r
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
output$plot1 <- renderPlot({
years <- c(1:10)
weight <- c(5,7,9,11,12,17,19,20,21,22)
group <- c(rep("A",5), rep("B",5))
df <- data.frame(years,weight,group)
df <- subset(df, group == input$ID)
total.weight <- sum(df$weight)
#Plot
ggplot(data=df, aes(x=df$years, y=df$weight)) +
geom_line() +
geom_point()
})
output$text1 <- renderText({total.weight})
})
Output snapshot:
You can also create reactives:
server.R
library(shiny)
library(ggplot2)
shinyServer(function(input, output) {
df <- reactive({
years <- c(1:10)
weight <- c(5,7,9,11,12,17,19,20,21,22)
group <- c(rep("A",5), rep("B",5))
df <- data.frame(years,weight,group)
df <- subset(df, group == input$ID)
})
total.weight <- reactive({
sum(df()$weight)
})
output$plot1 <- renderPlot({
#Plot
ggplot(data=df(), aes(x=years, y=weight)) +
geom_line() +
geom_point()
})
output$text1 <- renderText({total.weight()})
})
The quick workaround is to put the total weight in a global varaiable:
total.weight <<- sum(df$weight)
The nice way to do it is to subset your data.frame within a reactive function:
shinyServer(function(input, output) {
years <- c(1:10)
weight <- c(5,7,9,11,12,17,19,20,21,22)
group <- c(rep("A",5), rep("B",5))
df <- data.frame(years,weight,group)
reactive_df <- reactive(subset(df, group == input$ID))
output$plot1 <- renderPlot({
ggplot(data=reactive_df(), aes(x=years, y=weight)) +
geom_line() +
geom_point()
})
output$text1 <- renderText({sum(reactive_df()$weight)})
})