If we create all columns of factor characters with levels "A", "B", "C", "D", we can use xtabs without dropping any columns.
Unfortunately, the resulting matrix is not symmetrical.
library('tidyverse') df <- tribble( ~var1, ~var2, ~value, 'A', 'B', 4, 'C', 'D', 5, 'D', 'A', 2, 'B', 'D', 1 ) df %>% mutate_if(is.character, factor, levels=c('A', 'B', 'C', 'D')) %>% xtabs(value ~ var1 + var2, ., drop.unused.levels = F) # var2 # var1 ABCD # A 0 4 0 0 # B 0 0 0 1 # C 0 0 0 5 # D 2 0 0 0
To make it symmetrical, I just added its transpose to myself. However, this is a bit like hacks.
df %>% mutate_if(is.character, factor, levels=c('A', 'B', 'C', 'D')) %>% xtabs(value ~ var1 + var2, ., drop.unused.levels = F) %>% '+'(., t(.))