I have a data.table with following four columns:
col1 = as.numeric(0),
col2 = as.numeric(0),
col3 = as.numeric(0),
col4 = as.numeric(0)
In case of !is.na(df$col2) OR df$col2 != 0
col4 = col2 + col3
otherwise
col4 = col1 + col3
In frames of a shiny app I have used a nested ifelse() statement to do this conditional calculation. In this regard I have tried the following two versions of code but col4 is not getting a result in either of cases.
Can someone show me a right approach?
I went through several SO questions but could not effectively figure out how to use their solutions in my case.
The first version of my code:
library(shiny)
library(shinydashboard)
library(rhandsontable)
library(data.table)
DF <- data.table(
col1 = as.numeric(0),
col2 = as.numeric(0),
col3 = as.numeric(0),
col4 = as.numeric(0),
stringsAsFactors = FALSE
)
ui <- fluidPage(
dashboardPage(
dashboardHeader(),
dashboardSidebar(
menuItem("Calculation", tabName = "calc")
),
dashboardBody(
tabItems(
tabItem(tabName = "calc",
rHandsontableOutput("table")
)
)
)
)
)
server = function(input, output, session) {
data <- reactiveValues()
observe({ data$df <- as.data.table(DF) })
observeEvent(input$table, {
data$df[[4]] <- ifelse(
!is.na(data$df[[2]]) | data$df[[2]] != 0,
data$df[[2]] + data$df[[3]],
ifelse(
data$df[[2]]==NA | data$df[[2]] == 0,
data$df[[1]] + data$df[[3]],
NULL
)
)
})
output$table <- renderRHandsontable({
rhandsontable(data$df)
})
}
shinyApp(ui, server)
The second version of my code:
library(shiny)
library(shinydashboard)
library(rhandsontable)
library(data.table)
DF <- data.table(
col1 = as.numeric(0),
col2 = as.numeric(0),
col3 = as.numeric(0),
col4 = as.numeric(0),
stringsAsFactors = FALSE
)
ui <- fluidPage(
dashboardPage(
dashboardHeader(),
dashboardSidebar(
menuItem("Calculation", tabName = "calc")
),
dashboardBody(
tabItems(
tabItem(tabName = "calc",
rHandsontableOutput("table")
)
)
)
)
)
server = function(input, output, session) {
data <- reactiveValues()
observe({ data$df <- as.data.table(DF) })
output$table <- renderRHandsontable({
data$df[, col4 := ifelse(!is.na(data$df[[2]]) | data$df[[2]] != 0,
data$df[[2]] + data$df[[3]],
ifelse(data$df[[2]]== NA | data$df[[2]] == 0,
data$df[[1]] + data$df[[3]],
NULL))]
rhandsontable(data$df)
})
}
shinyApp(ui, server)
The issue why col4
is not updated is that in your code the reactiveValue
defined by data$df
is once initialized to as.data.table(DF)
(where DF
is your initial data frame) and then never gets updated with the current user-submitted values from the RHandsontable
. You can do this using hot_to_r
as done below, i.e. data$df <- as.data.frame(hot_to_r(input$table))
.
Unrelated here, but your if
condition does not make sense. If you say !is.na(df$col2) OR df$col2 != 0
and e.g. df$col2
is NA
, then the or
in the second part leads to NA
which breaks the output in column 4. You may need &
here or something else (below I used &
, note that FALSE & NA
evaluates to FALSE
and FALSE | NA
evaluates to NA
).
library(shiny)
library(shinydashboard)
library(rhandsontable)
library(data.table)
DF <- data.table(
col1 = as.numeric(0),
col2 = as.numeric(0),
col3 = as.numeric(0),
col4 = as.numeric(0),
stringsAsFactors = FALSE
)
ui <- fluidPage(
dashboardPage(
dashboardHeader(),
dashboardSidebar(
menuItem("Calculation", tabName = "calc")
),
dashboardBody(
tabItems(
tabItem(tabName = "calc",
rHandsontableOutput("table")
)
)
)
)
)
server = function(input, output, session) {
data <- reactiveValues(df = as.data.table(DF))
observeEvent(input$table, {
data$df <- as.data.frame(hot_to_r(input$table))
data$df[[4]] <- ifelse(
!is.na(data$df[[2]]) & data$df[[2]] != 0,
data$df[[2]] + data$df[[3]],
data$df[[1]] + data$df[[3]]
)
})
output$table <- renderRHandsontable({
rhandsontable(data$df)
})
}
shinyApp(ui, server)