Home > Software engineering >  Is it possible to conditionally format rows while using as_grouped_data with flextable?
Is it possible to conditionally format rows while using as_grouped_data with flextable?

Time:11-10

I'm trying to conditionally format rows after calling as_grouped_data basing the conditions on the grouped rows:

library(tidyverse)
library(flextable)

df <- tibble(vStat = c(rep("Average Degree", 3), rep("Average Weight", 3)),
             val = c(1.22222, 1.33333, 1.44444, 1.55555, 1.66666, 1.77777))

flextable(df %>%
            as_grouped_data(groups="vStat")) %>%
  colformat_double(i = ~ vStat=="Average Degree", digits=1) %>% # not working
  colformat_double(i = ~ vStat=="Average Weight", digits=3) %>% # not working
  autofit()

enter image description here

I understand that the above doesn't work because the condition in colformat_double only applies to rows where val is now NA:

df %>%
  as_grouped_data(groups="vStat")

>            vStat     val
> 1 Average Degree      NA
> 3           <NA> 1.22222
> 4           <NA> 1.33333
> 5           <NA> 1.44444
> 2 Average Weight      NA
> 6           <NA> 1.55555
> 7           <NA> 1.66666
> 8           <NA> 1.77777

It doesn't seem to work like grouped data normally would when calling first:

flextable(df %>%
            as_grouped_data(groups="vStat")) %>%
  colformat_double(i = ~ first(vStat=="Average Degree"), digits=1) %>%
  colformat_double(i = ~ first(vStat=="Average Weight"), digits=3) %>%
  autofit()

> Error in get_rows_id(x[[part]], i) : invalid row selection: length(i) [1] != nrow(dataset) [8]

Rounding in the dataset before grouping doesn't get me what I want either, with the number of digits still going out to the highest condition and getting filled in with zeros:

flextable(df %>%
            mutate(val = case_when(vStat=="Average Degree" ~ round(val, 1),
                                   vStat=="Average Weight" ~ round(val, 3))) %>%
            as_grouped_data(groups="vStat")) %>%
  autofit()

enter image description here

I'd really like to not have to specify individual row numbers in colformat_double in a table with 50 rows when my data change every day.

CodePudding user response:

We could create an index column or duplicate the same column 'vStat' with another name and do the condition on the index or use the same code on the other column and remove it later

library(dplyr)
library(flextable)
flextable(df %>%
            mutate(ind = match(vStat, unique(vStat))) %>%
            as_grouped_data(groups="vStat")) %>%
  colformat_double(i = ~ ind == 1, digits=1) %>% # not working
  colformat_double(i = ~ ind == 2, digits=3) %>% # not working
   void(j = ~ind) %>%
  compose( j = 3, value = as_paragraph(""), part = "header") %>%

  autofit()

-output

enter image description here

  • Related