Expand to blank with unnest

Viewed 73

I find SUPER useful for making results tables for a bunch of different variables. I was wondering if there was a way for the unnest() function (or otherwise) to expand a high order variable into blanks, rather than just repeating.

For example, with this code:

library(tidyverse)
data <- data.frame(
  group1 = sample(c('dog','cat', 'gecko'), 100, replace = T),
  group2 = sample(c('hot dog', 'not hotdog', 'other'), 100, replace = T)
)

my_freq <- function(var){
  result <- as.data.frame(table(data[[var]]))
  colnames(result) <- c('level', 'n')
  return(result)
}

the_table <- data.frame(var = c('group1', 'group2'))
the_table <- the_table %>% 
  mutate(
    result = map(var, my_freq)
  ) %>% 
  unnest(result)

Instead of the resulting table looking like:

enter image description here

It would look like this:

enter image description here

I guess this would be a multi-level index in , but not sure how to accomplish in .

3 Answers

Extending rmagno's solution to other high order variables

...%>%
  mutate_at(
    .vars = vars(high_order_vars),
    .funs = function(x) ifelse(duplicated(.[['var']]), NA, x)
  )

You could just use an lapply to get a list I call tb of the two tables. Then create a matrix with names(tb) in the first row and the rest blanks and convert it to a data frame. Finally Map assigns the desired names applying cbind on the columns of both data frames consecutively.

tb <- lapply(data, function(x) setNames(as.data.frame(table(x)), c("level", "n")))
res <- do.call(rbind, 
               Map(cbind, 
                   var=data.frame(
                     matrix(c(names(tb), rep("", (el(lapply(tb, nrow)) - 1)*2)),
                            ncol=2, byrow=TRUE)), 
                   tb))
res
#         var      level  n
# X1.1 group1        cat 31
# X1.2               dog 26
# X1.3             gecko 43
# X2.1 group2    hot dog 35
# X2.2        not hotdog 37
# X2.3             other 28

Not sure what you mean by blank (in this example I am going with NA). The critical line is:

mutate(var = if_else(!duplicated(var), var, NA_integer_))

Minimal working example:

library(tidyverse)
data <- data.frame(
  group1 = sample(c('dog','cat', 'gecko'), 100, replace = T),
  group2 = sample(c('hot dog', 'not hotdog', 'other'), 100, replace = T)
)

my_freq <- function(var){
  result <- as.data.frame(table(data[[var]]))
  colnames(result) <- c('level', 'n')
  return(result)
}

the_table <- data.frame(var = c('group1', 'group2'))
the_table <- the_table %>% 
  mutate(
    result = map(var, my_freq)
  ) %>% 
  unnest(result) %>%
  mutate(var = if_else(!duplicated(var), var, NA_integer_))

the_table
#> # A tibble: 6 x 3
#>   var    level          n
#>   <fct>  <fct>      <int>
#> 1 group1 cat           38
#> 2 <NA>   dog           38
#> 3 <NA>   gecko         24
#> 4 group2 hot dog       36
#> 5 <NA>   not hotdog    34
#> 6 <NA>   other         30

Created on 2020-02-29 by the reprex package (v0.3.0)

Related