I am new to R and Shiny package. I have a csv file with 4 col and 600 rows and I am trying to plot some graphs using ggplot2.
My ui and server codes are like:
dt<-read.csv('file.csv')
server <- function(input, output) {
output$aPlot <- renderPlot({
ggplot(data = dt, aes(x = Col1, y = Col2, group = 'Col3', color = 'Col4')) + geom_point()
})
}
ui <- fluidPage(sidebarLayout(
sidebarPanel(
sliderInput("Obs", "Log FC", min = 1, max = 600, value = 100)
),
mainPanel(plotOutput("aPlot")) ))
Here, I can get the ggplot output but I don't know how to use this slider input to control the number of rows to be read i.e., I want this "Obs" input to define the size of Col1 to be used in the graph.
Try something like this, example here is with mtcars dataset:
library(shiny)
library(ggplot2)
dt <- mtcars[,1:4]
ui <- fluidPage(
sidebarPanel(
sliderInput("Obs", "Log FC", min = 1, max = nrow(dt), value = nrow(dt)-10)
),
mainPanel(plotOutput("aPlot"))
)
server <- function(input, output) {
mydata <- reactive({
dt[1:as.numeric(input$Obs),]
})
output$aPlot <- renderPlot({
test <- mydata()
ggplot(data = test, aes(x = test[,1], y = test[,2], group = names(test)[3], color = names(test)[4])) + geom_point()
})
}
shinyApp(ui = ui, server = server)
Change your server to:
server <- function(input, output) {
observe({
dt_plot <- dt[1:input$Obs,]
output$aPlot <- renderPlot({
ggplot(data = dt_plot, aes(x = Col1, y = Col2, group = 'Col3', color = 'Col4')) + geom_point()
})
})
}
Related
I'm new in programming language especially R.
I have data frame and want to show top 3 of my data and sort from the biggest value using bar chart. I have tried some codes but failed to create proper chart. Here is my latest code :
library(shiny)
library(plotly)
my_data <- data.frame(x1 = c("a","b", "c","d","e","f","g","h"),
x2 = c(200, 200, 100,200,200,100,200,100),
x3 = c(100,400,500,50,100,300,100,50))
df1 <- my_data[order(my_data$x3),] #order by x3 value, to create rank
ui <- tabPanel("Test",
sidebarLayout(
sidebarPanel(
selectInput(inputId = "why",
label = "1. Select",
choices = df1$x2),
),
mainPanel(plotlyOutput("test"))
))
server <- function(input, output, session) {
output$test <- renderPlotly({
df2 <- df1 %>%
filter(x2 ==input$why) #filter by x2
p <-ggplot(df2,
aes(x = x1, y=x3)) +
geom_bar(stat = "identity")
fig <- ggplotly(p)
fig
})}
shinyApp(ui = ui, server = server)
the bar chart I created was not ordered correctly (based on x3 values), and I also only want to show top 3 of my data
To filter for the top 3 rows you could use dplyr::slice_max and to reorder your bars use e.g. reorder. Simply reordering the dataset will not work.
library(shiny)
library(dplyr)
library(plotly)
ui <- tabPanel(
"Test",
sidebarLayout(
sidebarPanel(
selectInput(
inputId = "why",
label = "1. Select",
choices = unique(df1$x2),
selected = 200
),
),
mainPanel(plotlyOutput("test"))
)
)
server <- function(input, output, session) {
output$test <- renderPlotly({
df2 <- df1 %>%
filter(x2 == input$why) %>%
slice_max(x3, n = 3, with_ties = FALSE)
p <- ggplot(
df2,
aes(x = reorder(x1, -x3), y = x3)
) +
geom_bar(stat = "identity")
fig <- ggplotly(p)
fig
})
}
shinyApp(ui = ui, server = server)
#>
#> Listening on http://127.0.0.1:8022
I know the question is already answered, but I encourage you to keep your server function as small as possible and try to wrap long series of code into functions.
Here is an example of what I mean
library(tidyverse)
library(shiny)
library(plotly)
my_data <- data.frame(x1 = c("a","b", "c","d","e","f","g","h"),
x2 = c(200, 200, 100,200,200,100,200,100),
x3 = c(100,400,500,50,100,300,100,50))
df1 <- my_data[order(my_data$x3),] #order by x3 value, to create rank
myPlot <- function(data, input) {
df <- data |>
filter(x2 == input) #filter by x2
p <-ggplot(df, aes(x = reorder(x1, -x3), y=x3)) +
geom_bar(stat = "identity")
return(ggplotly(p))
}
ui <- tabPanel("Test",
sidebarLayout(
sidebarPanel(
selectInput(inputId = "why",
label = "1. Select",
choices = df1$x2),
),
mainPanel(plotlyOutput("test"))
))
server <- function(input, output, session) {
output$test <- renderPlotly({
myPlot(df1, input$why)
})
}
shinyApp(ui = ui, server = server)
The ggplot just shows a vertical line of values that doesn't change when I try changing the x axis selection. The only thing on the x axis is the word "column" when I try to change the x axis, instead of the values of df$column according to what's selected.
df_variable <- df
df_colnames <- colnames(df)
xaxis_input <- selectInput(
inputId = "xaxis",
label = "Feature of Interest",
choices = df_colnames,
selected = df_colnames['default']
)
ui <- fluidPage(
titlePanel("DF"),
xaxis_input,
plotOutput(
outputId = "df_plot",
)
)
server <- function(input, output) {
output$df_plot <- renderPlot({
plot <- ggplot(data = df) +
geom_point(aes(x = input$xaxis, y = some_other_col))
return(plot)
})
}
input$xaxis is a string, so you cannot use it directly inside aes().
Try using aes_string() instead.
Note that some_other_col should also be a string.
server <- function(input, output) {
output$df_plot <- renderPlot({
plot <- ggplot(data = df) +
geom_point(aes_string(x = input$xaxis, y = "some_other_col"))
return(plot)
})
A full working example:
library(shiny)
library(ggplot2)
df <- iris
df_colnames <- colnames(df)
xaxis_input <- selectInput(
inputId = "xaxis",
label = "Feature of Interest",
choices = df_colnames
)
ui <- fluidPage(
titlePanel("DF"),
xaxis_input,
plotOutput(
outputId = "df_plot",
)
)
server <- function(input, output) {
output$df_plot <- renderPlot({
plot <- ggplot(data = df) +
geom_point(aes_string(x = input$xaxis, y = "Sepal.Width"))
return(plot)
})
}
# Run the application
shinyApp(ui = ui, server = server)
I'd like to include the reactive outputs of two data sets as different geom_lines in the same ggplotly figure. The code runs as expected when only one reactive data.frame is included as a geom_line. Why not two?
ui <- fluidPage(
sidebarLayout(
selectInput("Var1",
label = "Variable", #DATA CHOICE 1
selected = 10,
choices = c(10:100)),
selectInput("Var1",
label = "Variable2", #DATA CHOICE 2
selected = 10,
choices = c(10:100))
# Show a plot of the generated distribution
),
mainPanel(
plotlyOutput('plot') #Draw figure
)
)
server <- function(input, output) {
out <- reactive({
data.frame(x = rnorm(input$Var1), #Build data set 1
y = 1:input$Var1)
})
out2 <- reactive({
data.frame(x = rnorm(input$Var2), #Build data set 2
y = 1:input$Var2)
})
output$plot <- renderPlotly({
p <- ggplot() +
geom_line(data = out(), aes(x = x, y = y)) #Add both data sets in one ggplot
geom_line(data = out2(), aes(x = x, y = y), color = "red")
ggplotly(p)
})
}
# Run the application
shinyApp(ui = ui, server = server)
When you put the data into long format and give each group a group identifier it seems to work. Note that you should be able to change sliderInput back to selectInput - this was one of the entries I toggled during testing, but the choice of UI widget should not matter.
This works -- code can be simplified inside the reactive from here:
library(plotly)
ui <- fluidPage(
sidebarLayout(
sliderInput("Var1",
label = "Variable", #DATA CHOICE 1
min=10, max=100, value=10),
sliderInput("Var2",
label = "Variable2", #DATA CHOICE 2
min=10, max=100, value=10),
),
mainPanel(
plotlyOutput('plot') #Draw figure
)
)
server <- function(input, output) {
out <- reactive({
x1 <- rnorm(input$Var1)
y1 <- seq(1:input$Var1)
x2 <- rnorm(input$Var2)
y2 <- seq(1:input$Var2)
xx <- c(x1,x2)
yy <- c(y1,y2)
gg <- c( rep(1,length(y1)), rep(2,length(y2)) )
df <- data.frame(cbind(xx,yy,gg))
df
})
output$plot <- renderPlotly({
p <- ggplot() +
geom_line(data=out(), aes(x = xx, y = yy, group=gg, colour=gg))
ggplotly(p)
})
}
shinyApp(ui = ui, server = server)
I would like two plots to appear. First, a scatter plot and then a line graph. The graphs aren't important. This is my first time using Shiny. What is the best way to have both
plotOutput("needles"),
plotOutput("plot")
use the data from the same needles data frame? I think I'm getting confused as to how to pass the "needles" data frame between the plotOutput functions.
library(shiny)
library(tidyverse)
library(scales)
# Create the data frame ________________________________________________
create_data <- function(num_drops) {
needles <- tibble (
x = runif(num_drops, min = 0, max = 10),
y = runif(num_drops, min = 0, max = 10)
)
}
# Show needles ________________________________________________
show_needles <- function(needles) {
ggplot(data = needles, aes(x = x, y = y)) +
geom_point()
}
# Show plot __________________________________________________
show_plot <- function(needles) {
ggplot(data = needles, aes(x = x, y = y)) +
geom_line()
}
# Create UI
ui <- fluidPage(
sliderInput(inputId = "num_drops",
label = "Number of needle drops:",
value = 2, min = 2, max = 10, step = 1),
plotOutput("needles"),
plotOutput("plot")
)
server <- function(input, output) {
output$needles <- renderPlot({
needles <- create_data(input$num_drops)
show_needles(needles)
})
output$plot <- renderPlot({
show_plot(needles)
})
}
shinyApp(ui = ui, server = server)
We could execute the create_data inside a reactive call in the server and then within the renderPlot, pass the value (needles()) as arguments for show_needles and show_plot
server <- function(input, output) {
needles <- reactive({
create_data(input$num_drops)
})
output$needles <- renderPlot({
show_needles(needles())
})
output$plot <- renderPlot({
show_plot(needles())
})
}
shinyApp(ui = ui, server = server)
-output
I would really appreciate some help with the following code:
library(shiny)
library(rhandsontable)
library(tidyr)
dataa <- as.data.frame(cbind(rnorm(100, sd=2), rchisq(100, df = 0, ncp = 2.), rnorm(100)))
ldataa <- gather(dataa, key="variable", value = "value")
thresholds <- as.data.frame(cbind(1,1,1))
ui <- fluidPage(fluidRow(
plotOutput(outputId = "plot", click="plot_click")),
fluidRow(rHandsontableOutput("hot"))
)
server <- function(input, output) {
values <- reactiveValues(
df=thresholds
)
observeEvent(input$plot_click, {
values$trsh <- input$plot_click$x
})
observeEvent(input$hot_select, {
values$trsh <- 1
})
output$hot = renderRHandsontable({
rhandsontable(values$df, readOnly = F, selectCallback = TRUE)
})
output$plot <- renderPlot({
if (!is.null(input$hot_select)) {
x_val = colnames(dataa)[input$hot_select$select$c]
dens.plot <- ggplot(ldataa) +
geom_density(data=subset(ldataa,variable==x_val), aes(x=value), adjust=0.8) +
geom_rug(data=subset(ldataa,variable==x_val), aes(x=value)) +
geom_vline(xintercept = 1, linetype="longdash", alpha=0.3) +
geom_vline(xintercept = values$trsh)
dens.plot
}
})
}
shinyApp(ui = ui, server = server)
I have a plot and a handsontable object in the app.
Clicking on whichever cell loads a corresponding plot, with a threshold value. Clicking the plot changes the position of one of the vertical lines.
I would like to get the x value from clicking the plot into the corresponding cell, and I would like to be able to set the position of the vertical line by typing in a value in the cell too.
I'm currently a bit stuck with how I should feed back values into a reactiveValue dataframe.
Many thanks in advance.
This works as I imagined:
(The trick was to fill right columns of "df" with input$plot_click$x by indexing them with values$df[,input$hot_select$select$c].)
library(shiny)
library(rhandsontable)
library(tidyr)
dataa <- as.data.frame(cbind(rnorm(100, sd=2), rchisq(100, df = 0, ncp = 2.), rnorm(100)))
ldataa <- gather(dataa, key="variable", value = "value")
thresholds <- as.data.frame(cbind(1,1,1))
ui <- fluidPage(fluidRow(
plotOutput(outputId = "plot", click="plot_click")),
fluidRow(rHandsontableOutput("hot"))
)
server <- function(input, output) {
values <- reactiveValues(
df=thresholds
)
observeEvent(input$plot_click, {
values$df[,input$hot_select$select$c] <- input$plot_click$x
})
output$hot = renderRHandsontable({
rhandsontable(values$df, readOnly = F, selectCallback = TRUE)
})
output$plot <- renderPlot({
if (!is.null(input$hot_select)) {
x_val = colnames(dataa)[input$hot_select$select$c]
dens.plot <- ggplot(ldataa) +
geom_density(data=subset(ldataa,variable==x_val), aes(x=value), adjust=0.8) +
geom_rug(data=subset(ldataa,variable==x_val), aes(x=value)) +
geom_vline(xintercept = 1, linetype="longdash", alpha=0.3) +
geom_vline(xintercept = values$df[,input$hot_select$select$c])
dens.plot
}
})
}
shinyApp(ui = ui, server = server)
Update your reactiveValue dataframe from inside of an observeEvent, where you are watching for whichever event is useful, i.e. a click or something.
observeEvent(input$someInput{
values$df <- SOMECODE})