I am trying to do something that is quite simple to achieve in R script but I am struggling to replicate when part of a Shiny app. I am reading a file using ‘reactive({})’ (this part in the test code provided below has been replaced with test dataset, lines 13-16). I would like to take variable ‘Species’ entries and assign them to the data frame row names. I have tried two approaches
Inside the “reactive({})” statement, lines 13-16
By creating a new data frame df1, lines 18-20
but both ways don’t work for some reason.
Big thank you in advance!
library(shiny)
library(DT)
library(datasets)
ui <- basicPage("",
DT::dataTableOutput("table"),
verbatimTextOutput("head1"),
verbatimTextOutput("head2")
)
server <- function(input, output, session) {
df <- reactive({
df <- data.frame(v1=c("a", "b"), v2=c(10,20))
# row.names(df) <- df[,1] # THIS DOES NOT WORK
})
df1 <- reactive({ # THIS ALSO DOESN'T WORK
row.names(df()) <- df()[,1]
})
# Show data in a table ----
output$table <- DT::renderDataTable({
datatable(
{df()},
filter = 'top',
class="cell-border stripe",
rownames = TRUE
) # end of datatable
})
output$head1 <- renderPrint({
head(df())
})
output$head2 <- renderPrint({
head(df1())
})
}
shinyApp(ui = ui, server = server)
Try this
library(shiny)
library(DT)
library(datasets)
ui <- basicPage("",
DTOutput("table"),
DTOutput("head1"),
DTOutput("head2")
)
server <- function(input, output, session) {
df <- reactive({
df <- data.frame(v1=c("a", "b"), v2=c(10,20))
row.names(df) <- df[,1] # THIS WORKs
df
})
df1 <- reactive({ # THIS ALSO WORKs
data <- df()
row.names(data) <- df()[,1]
data
})
# Show data in a table ----
output$table <- renderDT({
datatable(
{df()},
filter = 'top',
class="cell-border stripe",
rownames = TRUE
) # end of datatable
})
output$head1 <- renderDT({
head(df())
})
output$head2 <- renderDT({
head(df1())
})
}
shinyApp(ui = ui, server = server)
Related
Trying to understand how to create observeEvent()'s to catch changes to an arbitrary number of dynamically-created RHandsontables. Has anyone successfully done this before?
The code below shows creation of the dynamic tables. The comments towards the bottom indicate the inputs I would like to track, but the observeEvents need to account for an arbitrary set of input names.
library(shiny)
library(dplyr)
library(rhandsontable)
library(purrr)
ui <- fluidPage(
uiOutput('tables')
)
server <- function(input, output) {
mtcars$slc <- sample(c('aaa','bbb'),nrow(mtcars),replace=TRUE)
df <- mtcars
getSlice <- function(df_tmp,slca){
print(slca)
df_tmp <- df_tmp %>% filter(slc==slca)
df_tmp
}
output$tables <- renderUI({
slices <- unique(df$slc)
input_dfs <- map(slices,~getSlice(df,.x))
for(i in 1:length(slices)){
local({
i <- i
print(input_dfs[[i]])
output[[slices[i]]] <- renderRHandsontable(rhandsontable(input_dfs[[i]]))
})
}
out <- map(slices,function(x){
rHandsontableOutput(x)
})
print(out)
out
})
### How do I create observeEvents for...
# input$aaa$changes$changes
# input$bbb$changes$changes
# input$arbitrarySlice$changes$changes
}
shinyApp(ui = ui, server = server)
You can iteratively add observeEvents using lapply() as shown:
library(shiny)
library(dplyr)
library(rhandsontable)
library(purrr)
ui <- fluidPage(
uiOutput("tables")
)
server <- function(input, output) {
mtcars$slc <- sample(c("aaa", "bbb"), nrow(mtcars), replace = TRUE)
df <- mtcars
getSlice <- function(df_tmp, slca) {
print(slca)
df_tmp <- df_tmp %>% filter(slc == slca)
df_tmp
}
output$tables <- renderUI({
slices <- unique(df$slc)
input_dfs <- map(slices, ~ getSlice(df, .x))
for (i in 1:length(slices)) {
local({
i <- i
print(input_dfs[[i]])
output[[slices[i]]] <- renderRHandsontable(rhandsontable(input_dfs[[i]]))
})
}
out <- map(slices, function(x) {
rHandsontableOutput(x)
})
print(out)
out
})
### How do I create observeEvents for...
# input$aaa$changes$changes
# input$bbb$changes$changes
# input$arbitrarySlice$changes$changes
### Iteratively add observeEvent()
lapply(unique(df$slc), function(slice) {
observeEvent(input[[slice]]$changes$changes, {
print(paste(slice, "has been updated!"))
print(input[[slice]][["changes"]])
})
})
}
shinyApp(ui = ui, server = server)
I am trying to use auto generated selectInput IDs inside the reactive element or observe event. When I explicitly write the input IDs like input$dfSelect1,input$dfSelect2,input$dfSelect3, it works as I wanted.
Since I don't know in advance how many IDs will be there (data will be user input), I need to create same input ID strings as automated, but it doesn't recognize it as a trigger in observe event or a input data in reactive element.
Here is the minimal reproducible example of my problem. if you comment out the line 1 req(input$dfSelect1,input$dfSelect2,input$dfSelect3) and line 2 dfx <- data.frame(carb = c(input$dfSelect1,input$dfSelect2,input$dfSelect3),stringsAsFactors = F) and remove the comment from the following lines, this will be the case I am trying to do.
any idea how to pass these values?
library(dplyr)
library(DT)
exdata <- head(mtcars, 3)
exdata$ROWs <- row.names(exdata)
ui <- fluidPage(
headerPanel("Example"),
mainPanel(
uiOutput("selectionUI"),
uiOutput("tableOutput")
)
)
server <- function(input, output, server) {
### reqString result <- input$dfSelect1,input$dfSelect2,input$dfSelect3
reqString <- noquote(paste0(unlist(lapply(1:length(sort(unique(row.names(exdata)))),function(i) {paste0("input$dfSelect",i,"")})),collapse = ","))
values <- reactiveValues(
upload_state = NULL
)
observe({
### 1-USE the line below with reqString instead -doesn't work ##
req(input$dfSelect1,input$dfSelect2,input$dfSelect3)
# req(reqString)
values$upload_state <- 'uploaded'
})
output$selectionUI <- renderUI({
df <- sort(unique(row.names(exdata)))
wellPanel(
lapply(1:length(df), function(i) {selectizeInput(paste0("dfSelect",i,""),df[i],choices=c("", unique(exdata$carb)))})
)
})
completeTable <- reactive({
browser()
if (is.null(values$upload_state)) {
return(exdata)
}else if (values$upload_state == 'uploaded') {
### 2-USE the line below with reqString instead -doesn't work##
dfx <- data.frame(carb = c(input$dfSelect1,input$dfSelect2,input$dfSelect3),stringsAsFactors = F)
# dfx <- data.frame(carb = c(reqString),stringsAsFactors = F)
dfx <- data.frame(carb =as.numeric(unlist(dfx)))
dataJoin <- exdata %>% left_join(dfx,by=("carb"))
}
})
output$tableOutput <- renderUI({
DT::dataTableOutput("dataTableServer")
})
output$dataTableServer <- DT::renderDataTable({
DT::datatable(completeTable())
})
}
shinyApp(ui = ui, server = server)
You can index input using [[ instead of $:
sapply(1:length(sort(unique(row.names(exdata)))),
FUN=function(x) req(input[[paste0("dfSelect", x)]]))
and
l <- sapply(1:length(sort(unique(row.names(exdata)))),
FUN=function(x) input[[paste0("dfSelect", x)]])
dfx <- data.frame(carb = l,stringsAsFactors = F)
In my reactive dataframe, one column has a reactive name (chosen by the user) and I would like to generate a column whose values are the logarithm of the original column. To do so, I use mutate in the dplyr package. However, when I try to make the name of this new column reactive, there's an error.
For example, in the code below, I name the new column "logarithm" and it works fine:
library(shiny)
library(DT)
library(data.table)
library(dplyr)
ui <- fluidPage(
titlePanel(""),
fluidRow(
checkboxInput(inputId = "logarithm",
label = "Log(variable)"),
dataTableOutput("my_df"),
textInput("new_name",
label = "New_name"),
actionButton("new_name2", "Validate")
)
)
server <- function(input, output) {
data <- head(mtcars[, 1:3])
reactive_data <- eventReactive(input$new_name2, {
colnames(data) <- c("mpg", "cyl", input$new_name)
data
})
output$my_df <- renderDataTable({
data <- reactive_data()
if(input$logarithm){
data %>%
mutate(logarithm = log(data[, input$new_name]))
}
else {
data
}
})
}
shinyApp(ui = ui, server = server)
But change "logarithm" by "logarithm(input$new_name)" and it won't work anymore.
Does anybody have a solution?
Based on this question and answer
if(input$logarithm){
log_name <- paste0('logarithm(', input$new_name, ')')
data %>%
mutate(!!log_name := log(data[, input$new_name]))
}
Full code:
library(shiny)
library(DT)
library(data.table)
library(dplyr)
ui <- fluidPage(
titlePanel(""),
fluidRow(
checkboxInput(inputId = "logarithm",
label = "Log(variable)"),
dataTableOutput("my_df"),
textInput("new_name",
label = "New_name"),
actionButton("new_name2", "Validate")
)
)
server <- function(input, output) {
data <- head(mtcars[, 1:3])
reactive_data <- eventReactive(input$new_name2, {
colnames(data) <- c("mpg", "cyl", input$new_name)
data
})
output$my_df <- renderDataTable({
data <- reactive_data()
if(input$logarithm){
log_name <- paste0('logarithm(', input$new_name, ')')
data %>%
mutate(!!log_name := log(data[, input$new_name]))
}
else {
data
}
})
}
shinyApp(ui = ui, server = server)
In the below toy example I have a data set datapred. The data set are output to an interactive table using rhandsontable. Then I covert it in a new data.frame with hot_to_r. My issue is that when I wnat to use it in my function prediction(), it send me an error message and the application crash. I don't understand why.
I'm french so I converted in english the message :
Error in as.name: the 'pairlist' object can not be automatically converted to a 'symbol' type.
library(shiny)
library(frailtypack)
library(rhandsontable)
data("readmission", package = "frailtypack")
ui <- fluidPage(
titlePanel("prediction"),
mainPanel(
fluidRow(rHandsontableOutput("hot")),
br(),
plotOutput("pred")
)
)
server <- function(input, output) {
newdata <- subset(readmission,select = c("time","event","id","dukes"))
datapred <- newdata[1,]
data <- reactive({
DF = hot_to_r(input$hot)
DF
})
model <- frailtyPenal(Surv(time,event)~cluster(id)+dukes,n.knots=10,
kappa=10000,data=readmission)
predict <- reactive(
prediction(model, data(),t=200,window=seq(50,1900,50),
MC.sample=100))
output$hot <- renderRHandsontable({
rhandsontable(datapred)
})
data <- reactive({
DF = hot_to_r(input$hot)
DF
})
output$pred <- renderPlot({
plot(predict(),conf.bands=TRUE)
})
}
shinyApp(ui = ui, server = server)
You could simply evaluate the data() first, like this. I also added some checks so you don't get other errors during the initialization
library(shiny)
library(frailtypack)
library(rhandsontable)
data("readmission", package = "frailtypack")
ui <- fluidPage(
titlePanel("prediction"),
mainPanel(
fluidRow(rHandsontableOutput("hot")),
br(),
plotOutput("pred")
)
)
server <- function(input, output) {
newdata <- subset(readmission,select = c("time","event","id","dukes"))
datapred <- newdata[1,]
data <- reactive({
hot <- input$hot
if (!is.null(hot)) hot_to_r(hot)
})
model <- frailtyPenal(Surv(time,event)~cluster(id)+dukes,n.knots=10,
kappa=10000,data=readmission)
predict <- reactive({
dat <- data()
if (!is.null(dat)) {
prediction(model, dat,t=200,window=seq(50,1900,50),
MC.sample=100)
}
})
output$hot <- renderRHandsontable({
rhandsontable(datapred)
})
output$pred <- renderPlot({
pred <- predict()
if (!is.null(pred)) plot(pred, conf.bands = TRUE)
})
}
shinyApp(ui = ui, server = server)
I've had some luck with Shiny and R, but I can't get an selectInput function to change the dataframe. I'm probably missing something obvious, but here's my code
require(shiny)
A <- data.frame(x=c(1,2,3),y=c(3,2,1))
B <- data.frame(x=c(1,1,5),y=c(3,5,0))
ui <- fluidPage(
selectInput("df", "Select dataframe", choices = c('A'='A','B'='B'), selected = 'A'),
plotOutput("Plot")
)
server <- function(input, output)
{
df <- reactive({
x <- as.data.frame(input$df)
})
output$Plot <- renderPlot({
df <- df()
plot(x=df$x, y=df$y)
})
}
shinyApp(ui = ui, server = server)
What am I missing?
You cant use as.data.frame and name of df
try to use get
A <- data.frame(x=c(1,2,3),y=c(3,2,1))
B <- data.frame(x=c(1,1,5),y=c(3,5,0))
shinyServer(function(input, output) {
df <- reactive({
x <- get(input$df)
})
output$Plot <- renderPlot({
df <- df()
plot(x=df$x, y=df$y)
})
})