I’m trying to rename multiple values in a data frame, using R, Shiny, and rhandsontable. A description of the problem follows.
Toy Data Frame:
I’d like to be able to
With the possibility of returning to any of the variables and continue with renaming.
In the real world example the number of variables and the values associated with each variable aren’t known ahead of time.
The current version of the Shiny app I’m building is attached. I’m using rhandsontable (https://github.com/jrowen/rhandsontable) to support the renaming, patterning the renaming steps after the rhandsontable_datafile (rhandsontable/inst/examples) example provided by jrowen.
I am able to select one of the three variables and rename its values. I am not able to then select one of the other two variables and proceed with renaming values. Once I select the ‘Commit’ button the rhandsontable no longer updates to reflect the selected variable.
Any help / suggestions would be greatly appreciated.
.....code.....
##
## Home > R > brickyard > FindAndReplace
##
## table renaming based on the work of Jonathan Owen
## [github] jrowen / rhandsontable & examples therein
library(shiny)
library(magrittr)
library(rhandsontable)
library(dplyr)
##### build toy data frame
colors <- data.frame(sample(c('red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet'),
100, replace = TRUE))
colnames(colors) <- c("color")
colors$color <- as.character(colors$color)
teams <- data.frame(sample(c("Orioles", "RedSox", "BlueJays", "Yankees", "Rays"),
100, replace = TRUE))
colnames(teams) <- c("ALeast")
teams$ALeast <- as.character(teams$ALeast)
states <- data.frame(sample(c("ME", "VT", "NH", "MA", "CT", "RI"),
100, replace = TRUE))
colnames(states) <- c("NewEngland")
states$NewEngland <- as.character(states$NewEngland)
df <- data.frame(cbind(colors, teams, states))
vars <- names(df)
##
## UI
##
ui <- shinyUI(fluidPage(
uiOutput("choose_var"),
DT::dataTableOutput(outputId = "recoding"),
actionButton("commitButton", "Commit"),
rHandsontableOutput("hot"),
DT::dataTableOutput(outputId = "newVars")
))
##
## SERVER
##
server <- shinyServer(function(input, output) {
##### choose variable for value renaming
output$choose_var <- renderUI({
radioButtons(inputId = "var",
label = "Select column to recode",
choices = vars)
})
output$selectedVar <- renderText(input$var)
##### build a (reactive) 2-column data frame with a variable's unique values
##### the idea being the left hand column presents the initial values, and the
##### right hand column presents values the user is meant rename ... initially,
##### both columns hold the same content
#####
##### these renamed values will be used in updating the entire data frame
#####
recodeValues <- reactive({
if(is.null(input$var)) {return()}
uniqueVars <- df %>% select_(input$var) %>% unique()
convert <- cbind(uniqueVars, uniqueVars)
colnames(convert) <- c("original", "convert")
convert
})
##### display the data frame - making sure data is updating
output$recoding <- DT::renderDataTable({
recodeValues()
})
##### the following code is based on Jonathan Owen's rhandsontable package
##### see his rhandsontable_datafile example
fname = tempfile()
values = list()
setHot = function(x) values[["hot"]] <<- x
observe({
input$commitButton
if (!is.null(values[["hot"]])) {
write.csv(values[["hot"]], fname)
print(fname)
##### use the recoded values to rename values throughout the entire data frame
recodes <- read.csv(fname, stringsAsFactors = FALSE)
for(i in 1:nrow(recodes)){
if(recodes[i,2] != recodes[i,3]){
df[df == recodes[i,2]] <- recodes[i,3]
}
}
output$newVars <- DT::renderDataTable({
df
})
}
})
output$hot = renderRHandsontable({
if (!is.null(input$hot)) {
DF = hot_to_r(input$hot)
} else {
if(is.null(input$var)) {return()}
DF = recodeValues()
}
setHot(DF)
rhandsontable(DF) %>%
hot_table(highlightCol = TRUE, highlightRow = TRUE)
})
}
)
##
## Run the application
##
shinyApp(ui = ui, server = server)