I would like to be able to calculate a new column of data based on dividing one column by another, with both original columns selected by a user input. I would like to have this calculated data joined to the original table (or a copy of it).
I have managed to figure out how to make a dataframe that reacts to the column input selection, and I have managed to make a calculation that divides one column by the other, but I have not been able to make a final dataframe that includes all of the original columns as well as the new calculated one.
Here is a mock up I have made using the built in Iris data. It displays the data for the columns selected in the first table, and the calculation in the second table (you will need to scroll down quite far to see this).
How can I join this calculated data to the original source?
Many thanks
#Ui
pageWithSidebar(
headerPanel('Calculate Column'),
sidebarPanel(
#select variables from iris dataset
selectInput('xcol', 'X Variable', names(iris)),
selectInput('ycol', 'Y Variable', names(iris),
selected=names(iris)[[2]])
),
mainPanel(
#display the selected variables
tableOutput("view"),
#display the calculated variable
tableOutput("view2")
)
)
#Server
function(input, output, session) {
# Combine the selected input variables into a new data frame
selectedData <- reactive({
iris[, c(input$xcol, input$ycol),]
})
# divide one variable selection by the other
selectedData2 <- reactive({
iris$new<-iris[, c(input$xcol)]/iris[, c(input$ycol)]
})
# create data output for selected variables
output$view <- renderTable({selectedData()
})
# create data output for calculated variable
output$view2 <- renderTable({selectedData2()
})
}
You forget that iris
is NOT a reactive element, so your code can't work. You have two options here:
reactive()
.reactiveValues()
. Using reactiveValues
you can make a list of reactive expressions much like input
and output
are. In the example below I use it to store the data frame iris
as globals$mydf
. Then you can use eg observe
to change the value reactively, as in the following server function:
#Server
server <- function(input, output, session) {
globals <- reactiveValues(
mydf = iris
)
observe({
thedf <- globals$mydf
newvar <- thedf[[input$xcol]] / thedf[[input$ycol]]
globals$mydf$ratio <- newvar
})
# create data output for selected variables
output$view <- renderTable({
globals$mydf
})
}
You can make two reactive expressions that depend on eachother:
Your server would look like this :
server <- function(input, output, session) {
newdf <- reactive({
cbind(
iris[c(input$xcol, input$ycol)],
Ratio = newvar()
)
})
newvar <- reactive({
iris[[input$xcol]] / iris[[input$ycol]]
})
# create data output for selected variables
output$view <- renderTable({
newdf()
})
}
Although you beliefe this is not what you're looking for, you can use newdf()
in other code just like you would use globals$mydf
in the previous example. reactiveValues()
especially pays off if different parts of your code have to be able to change the data frame.
You don't return anything in your reactive
for selectedData2
you just do an incrementation <-
, I think you should do this :
function(input, output, session) {
# Combine the selected input variables into a new data frame
selectedData <- reactive({
return(iris[, c(input$xcol, input$ycol),])
})
# divide one variable selection by the other
selectedData2 <- reactive({
new<-iris[, c(input$xcol)]/iris[, c(input$ycol)]
return(new)
})
# create data output for selected variables
output$view <- renderTable({selectedData()
})
# create data output for calculated variable
output$view2 <- renderTable({selectedData2()
})
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With