Q: Counting unique character values in grouped dataframe: dplyr::count(), stringr::str_count() and/or purrr::map() Building upon Error using dplyr::count() within purrr::map()
I want dataframes of counts unique character values by subsets of rows
Full dataset is 1000+ rows, many tumour types
Toy example:
library(tidyverse)

df <- tibble::tribble(
  ~tumour, ~impact.on.surgery, ~impact.on.radiotherapy, ~impact.on.chemotherapy, ~impact.on.biologics, ~impact.on.immunotherapy,
  'Breast', NA,               NA,               NA,               'Interrupted',      NA,               
  'Breast', NA,               NA,               NA,               'As.planned',       NA,               
  'Breast', NA,               NA,               NA,               'Interrupted',      NA,               
  'Breast', NA,               NA,               'As.planned',     NA,                NA,               
  'Breast', NA,               NA,               NA,               NA,               NA,               
  'Breast', NA,               NA,               NA,               'Interrupted',      NA             

> df
# A tibble: 6 x 6
  tumour impact.on.surgery impact.on.radiotherapy impact.on.chemotherapy impact.on.biologics impact.on.immunotherapy
  <chr>  <lgl>             <lgl>                  <chr>                  <chr>               <lgl>                  
1 Breast NA                NA                     NA                     Interrupted         NA                     
2 Breast NA                NA                     NA                     As.planned          NA                     
3 Breast NA                NA                     NA                     Interrupted         NA                     
4 Breast NA                NA                     As.planned             NA                  NA                     
5 Breast NA                NA                     NA                     NA                  NA                     
6 Breast NA                NA                     NA                     Interrupted         NA                     
)

Desired output:
Ideally as a named list of dataframes by tumour type, so I can then later reduce(bind_rows, .id = 'tumour') appending a .id column label
$ Breast
# A tibble: 2 x 6
  impact      impact.on.surgery impact.on.radiotherapy impact.on.chemotherapy impact.on.biologics impact.on.immunotherapy
  <chr>                   <dbl>                  <dbl>                  <dbl>               <dbl>                   <dbl>
1 Interrupted                 0                      0                      0                   3                       0
2 As.planned                  0                      0                      1                   1                       0

Tried so far:
# Gets single row tibble, but not sure how to `.id` label each row, map across all values & bind
df %>%   
  summarise(across(starts_with('impact'), ~sum(str_count(.x, 'As.planned'), na.rm = T)))

# A tibble: 1 x 5
  impact.on.surgery impact.on.radiotherapy impact.on.chemotherapy impact.on.biologics impact.on.immunotherapy
              <int>                  <int>                  <int>               <int>                   <int>
1                 0                      0                      1                   1                       0

# ?Counts all variable values (no need to specify), simpler code, but also counts `NAs` and I can't pivot that to a wide form as it has 'counted' the tumour
df %>% 
  map_dfr(~count(data.frame(x=.), x), .id = 'var')

                      var           x n
1                  tumour      Breast 6
2       impact.on.surgery        <NA> 6
3  impact.on.radiotherapy        <NA> 6
4  impact.on.chemotherapy  As.planned 1
5  impact.on.chemotherapy        <NA> 5
6     impact.on.biologics  As.planned 1
7     impact.on.biologics Interrupted 3
8     impact.on.biologics        <NA> 2
9 impact.on.immunotherapy        <NA> 6


A: An option with map would be to loop over the elements to be counted i.e. "Interrupted", "As.planned", then use summarise across the columns that starts_with prefix names 'impact' after grouping by 'tumour', get the frequency count by taking the sum of logical vector in each column
library(dplyr)
library(purrr)
library(stringr)
map_dfr(dplyr::lst('Interrupted', 'As.planned'), ~
     df %>%
        group_by(tumour) %>% 
        summarise(across(starts_with('impact'), function(x)
             sum( x == .x, na.rm = TRUE)), .groups = 'drop'), .id = 'impact') %>%
     mutate(impact = str_remove_all(impact, '"'))
# A tibble: 2 x 7
#  impact      tumour impact.on.surgery impact.on.radiotherapy impact.on.chemotherapy impact.on.biologics impact.on.immunotherapy
#  <chr>       <chr>              <int>                  <int>                  <int>               <int>                   <int>
#1 Interrupted Breast                 0                      0                      0                   3                       0
#2 As.planned  Breast                 0                      0                      1                   1                       0


Or to avoid getting the quotes around the values, use setNames instead of lst
map_dfr(setNames(c('Interrupted', 'As.planned'),
       c('Interrupted', 'As.planned')),  ~
      df %>%
        group_by(tumour) %>% 
         summarise(across(starts_with('impact'), function(x)
              sum( x == .x, na.rm = TRUE)), .groups = 'drop'), .id = 'impact')


Or using base R
lst1 <- lapply(c("Interrupted", "As.planned"), 
    function(x) aggregate(.~ tumour, df, FUN = function(y)
    sum(y == x, na.rm = TRUE), na.action = NULL))

data.frame(impact = c("Interrupted", "As.planned"), do.call(rbind, lst1))
#     impact tumour impact.on.surgery impact.on.radiotherapy impact.on.chemotherapy impact.on.biologics impact.on.immunotherapy
#1 Interrupted Breast                 0                      0                      0                   3                       0
#2  As.planned Breast                 0                      0                      1                   1                       0

