How might I (recursively) rename multiple values in a data frame

446 views
Skip to first unread message

Pawel

unread,
Jul 30, 2016, 12:24:58 PM7/30/16
to Shiny - Web Framework for R

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:

  • 100 observations of 3 variables. The variables are color, sampled from red, orange, yellow, green, blue, indigo, and violet;
  • ALeast, sampled from Orioles, RedSox, BlueJays, Yankees, and Rays; and
  • NewEngland, sampled from ME, VT, NH, MA, CT, and RI.

 

I’d like to be able to

  • rename every instance of ‘blue’ to read ‘cyan’, followed by
  • renaming every instance of ‘Yankees’ to read ‘Mets, followed by
  • renaming every instance of ‘ME’ to read ‘Maine’.

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)

Reply all
Reply to author
Forward
0 new messages