Search code examples
rflextable

Remove whitespace from formatted flextable columns


I want to convert this data to a flextable, format the columns, and save as an image for reporting purposes:

library(flextable)
library(dplyr)

df = data.frame(col1 = c(10,1,0,0.1,-0.5,-100, NA),
                col2 = c(1,1,0,0.1,-0.5,-1, NA),
                col3 = c(10,1,0,0.1,-0.5,-10000.90, NA),
                col4 = c(10,1,0,0.1,-0.5,-100, NA)
)

formater_for_ft = function(x){
    ifelse(x < 0, paste0("(",format(round(as.numeric(abs(x)), 1), 
                                    nsmall=1, big.mark=","),")"),
           ifelse(x == 0, paste("-"),
                  ifelse(is.na(x), "",
                         ifelse(x > 100,
                                format(round(as.numeric(x), 1), nsmall=1, big.mark=","),
                                format(round(as.numeric(x), 1), nsmall=1)))))
  }

ft = df %>% 
  flextable() %>%
  set_formatter(col1 = function(x) formater_for_ft(x)) %>%
  set_formatter(col2 = function(x) formater_for_ft(x)) %>%
  set_formatter(col3 = function(x) formater_for_ft(x)) %>%
  set_formatter(col4 = function(x) formater_for_ft(x))
ft
save_as_image(ft,
              path = "/home/app/mre.png",
              zoom = 3 ,
              webshot = "webshot2")

This looks almost acceptable in the viewer:

But the saved image there is leading whitespaces in the 4th row of the 1st, 3rd and 4th columns:

I would like it to look like the 4th row and 2nd column

Is there something that can be done to solve this issue?

for reference I am running in a docker container using rocker/verse


Solution

  • The problem is that your function is leaving a space when it substitutes the negative signs. Use the str_remove_all function from the stringr package to remove all spaces. Example:

    df <-  data.frame(col1 = c(10,1,0,0.1,-0.5,-100, NA),
                    col2 = c(1,1,0,0.1,-0.5,-1, NA),
                    col3 = c(10,1,0,0.1,-0.5,-10000.90, NA),
                    col4 = c(10,1,0,0.1,-0.5,-100, NA)
    )
    
    
    formater_for_ft = function(x){
      ifelse(x < 0, 
             stringr::str_remove_all(                            # Here
        paste0("(",format(round(as.numeric(abs(x)), 1), 
                          nsmall=1, big.mark=","),")"), 
        " "),                                                    # Here
        ifelse(x == 0, paste("-"),
                    ifelse(is.na(x), "",
                           ifelse(x > 100,
                                  format(round(as.numeric(x), 1), nsmall=1, big.mark=","),
                                  format(round(as.numeric(x), 1), nsmall=1)))))
    }
    
    
    ft <-  df %>% 
      flextable() %>%
      set_formatter(col1 = function(x) formater_for_ft(x)) %>%
      set_formatter(col2 = function(x) formater_for_ft(x)) %>%
      set_formatter(col3 = function(x) formater_for_ft(x)) %>%
      set_formatter(col4 = function(x) formater_for_ft(x))
      
    ft
    save_as_image(ft,
                  path = "mre.png",
                  zoom = 3 ,
                  webshot = "webshot2")
    

    Outputs: enter image description here