Search code examples
rflextable

Programming with flextable


I have a function that generates dataframes with the following structure:

df <- data.frame(selected.variable = paste(letters[1:5], '_'),
             percentage = c(50, 20, 10, 10, 10))

from a much larger dataframe.

That is, in the dataframes I am working with there is one column with the labels for the selected variable and a second column that gives the percentage of cases in which that label occurs.

I want to create tables of these dataframes using the package flextable https://github.com/davidgohel/flextable. I can do this directly using code like the following:

percent_format <- function(x){
  sprintf("%.1f %%", x)
}

labels_format <- function(x) {
  x <- gsub(pattern = '_', replacement = '', x = x)
  return(x)
}

table <- regulartable(df) 
table <- set_header_labels(table, selected.variable = 'New name', percentage = 'Percentage')
table <- set_formatter(table, selected.variable = labels_format, 
                       percentage = percent_format)

I would like to write a function that updates the name and format of the selected variable programmatically - something like this:

make.flextable <- function(data, variable, variable.name) {

percent_format <- function(x){
      sprintf("%.1f %%", x)
    }

    labels_format <- function(x) {
      x <- gsub(pattern = '_', replacement = ' ', x = x)
      return(x)
    }

    table <- regulartable(data) 
    table <- set_header_labels(table, variable = variable.name, percentage = 'Percentage')
    table <- set_formatter(table, variable = labels_format, 
                           percentage = percent_format)

return(table)
} 

However, I cannot work out how to pass the name of the selected variable (e.g., "selected.variable" in example above) to flextable. I have tried to use the map2 function as per this question:

In nested data frame, pass information from one list column to function applied in another

but have not been able to make it work.


Solution

  • Since few days, a new version is available on github (soon on cran), please update if possible as the below code is only tested with the new version. I am not sure this was what you wanted but at least the example show some code that could be reused :

    library(flextable)
    
    labels_format <- function(x) {
      x <- gsub(pattern = '_', replacement = ' ', x = x)
      return(x)
    }
    percent_format <- function(x){
      sprintf("%.1f %%", x)
    }
    
    
    make.flextable <- function(data, percent_variables, label_variables, labels ) {
    
      table <- flextable(data) 
    
      table <- set_header_labels(table, values = labels)
    
      # a simple function to format number
      table <- colformat_num(table, col_keys = percent_variables, digits = 1, suffix = "%" )
    
      # how to do with labels_format, create a named list
      args <- rep(list(labels_format), length(label_variables))
      names(args) <- label_variables
    
      # older versions :
      # table <- do.call(set_formatter, append(args, list(x=table) ) )
      table <- set_formatter(table, values = args )
    
      table <- set_header_labels(table, values = labels)
      # older versions :
      # table <- do.call(set_header_labels, append(labels, list(x=table) ) )
      return(autofit(table))
    } 
    
    df <- data.frame(selected.variable = paste(letters[1:5], '_'),
                     percentage = c(50, 20, 10, 10, 10), stringsAsFactors = FALSE)
    ft <- make.flextable(df, 
                   percent_variables = 'percentage', 
                   label_variables = "selected.variable", 
                   labels = list(selected.variable = "new name", 
                                 percentage = "Percentage"
                                 ))
    
    print(ft)
    

    enter image description here