3

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")
jay.sf
  • 60,139
  • 8
  • 53
  • 110
Sana
  • 65
  • 6

2 Answers2

4

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)).

Maël
  • 45,206
  • 3
  • 29
  • 67
  • 6
    I know you've answered the question with the the type of data OP described, but if possible they would be better off going back a step and stacking before using `table()`, e.g. `table(stack(mtcars[c("vs", "cyl", "gear")]))`. – Ritchie Sacramento Jul 24 '23 at 07:37
  • 2
    Indeed! Good point. This should be the accepted answer actually. Much easuer – Maël Jul 24 '23 at 07:41
  • Thank you so much. It worked. thanks again – Sana Jul 24 '23 at 07:47
  • Both answers worked actually but it was much simpler. – Sana Jul 24 '23 at 07:49
1

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")
jay.sf
  • 60,139
  • 8
  • 53
  • 110
  • Thank you so much. This solution worked too along with the previously suggested answers. – Sana Jul 25 '23 at 00:53