How to column-bind frequency tables with different column numbers?

64 Views Asked by At

I have a frequency table that has different column numbers. I am using the following code but it is not resulting in accurate results.

data_cbind <- cbind(table_45_1, table_45_3, table_45_6 table_45_12) 

head(table_45_1)
 1  2  3 
30  4  1 

head(table_45_3)
 1  2  3  4 
10  8  1  1 

head(table_45_6)
 1  2 
 12  5

head(table_45_12)
 1   
 1  

I want to organize the data as follows:

enter image description here

data

table_45_1 <- structure(c(`1` = 30L, `2` = 4L, `3` = 1L), dim = 3L, dimnames = structure(list( c("1", "2", "3")), names = ""), class = "table")
table_45_3 <- structure(c(`1` = 10L, `2` = 8L, `3` = 1L, `4` = 1L), dim = 4L, dimnames = structure(list( c("1", "2", "3", "4")), names = ""), class = "table")
table_45_6 <- structure(c(`1` = 12L, `2` = 5L), dim = 2L, dimnames = structure(list( c("1", "2")), names = ""), class = "table")
table_45_12 <- structure(c(`1` = 1L), dim = 1L, dimnames = structure(list("1"), names = ""), class = "table")
2

There are 2 best solutions below

1
jay.sf On BEST ANSWER

Here's a way to rbind frequency "table"s with unequal lengths. Essentially we add an id column and reshape.

mget(l <- ls(pattern='table_')) |>
  lapply(as.data.frame) |>
  Map(`[<-`, x=_, 'id', value=l) |>
  suppressWarnings() |>  ## *
  do.call(what='rbind') |>
  reshape(direction='wide', timevar='Var1', new.row.names=l) |>
  subset(select=-id) |>
  t()
#        table_45_1 table_45_12 table_45_3 table_45_6
# Freq.1         30           1         10         12
# Freq.2          4          NA          8          5
# Freq.3          1          NA          1         NA
# Freq.4         NA          NA          1         NA

*As for the warning, see here.


Data:

table_45_1 <- structure(c(`1` = 30L, `2` = 4L, `3` = 1L), dim = 3L, dimnames = structure(list( c("1", "2", "3")), names = ""), class = "table")
table_45_3 <- structure(c(`1` = 10L, `2` = 8L, `3` = 1L, `4` = 1L), dim = 4L, dimnames = structure(list( c("1", "2", "3", "4")), names = ""), class = "table")
table_45_6 <- structure(c(`1` = 12L, `2` = 5L), dim = 2L, dimnames = structure(list( c("1", "2")), names = ""), class = "table")
table_45_12 <- structure(c(`1` = 1L), dim = 1L, dimnames = structure(list("1"), names = ""), class = "table")
3
Maël On

You can create a list of tables, then stack them, and use Reduce to merge them altogether:

#Mock data
tab1 <- table(mtcars$vs)
tab2 <- table(mtcars$cyl)
tab3 <- table(mtcars$gear)

lapply(mget(ls(pat = "^tab")), stack) |>
  Reduce(f = \(x, y) merge(x, y, by = "ind", all = TRUE))

To get a nicer output, you can even use as.data.frame.table instead of stack which has a responseName argument (see as.data.frame(tab1, responseName = "cyl)).