Tiago Bruno
Tiago Bruno

Reputation: 413

How can I convert a list of tables to a data.frame in R?

Having a named list such as :

set.seed(1)
list <- list(table(sample(LETTERS[1:10], 50, replace = T)), table(sample(LETTERS[1:20], 50, replace = T)))
names(list) <- LETTERS[1:2]

How can one convert this list into a data frame that fills the gaps with the element's names?

For example, the code below gives an error due to different row numbers:

as.data.frame(list)

Error in (function (..., row.names = NULL, check.rows = FALSE, check.names = TRUE,  : 
  arguments imply differing number of rows: 10, 18

manually is possible for this small table by doing like this:

rbind(data.frame(Name = "A", Letters = list$A), data.frame(Name = "B", Letters = list$B))
   Name Letters.Var1 Letters.Freq
1     A            A            3
2     A            B            3
3     A            C            3
4     A            D            4
5     A            E            6
6     A            F            6
7     A            G            6
8     A            H            3
9     A            I            8
10    A            J            8
11    B            A            3
12    B            B            2
13    B            D            1
14    B            F            4
15    B            G            5
16    B            H            4
17    B            I            1
18    B            J            3
19    B            K            3
20    B            L            3
21    B            M            4
22    B            N            3
23    B            O            1
24    B            P            4
25    B            Q            2
26    B            R            2
27    B            S            4
28    B            T            1

Would you know how to scale this for a list with dozens of tables?

Thanks for the help.

Upvotes: 1

Views: 178

Answers (2)

Ian Campbell
Ian Campbell

Reputation: 24790

If you prefer data.table:

library(data.table)
rbindlist(Map(stack,list),idcol = "Name")
#   Name values ind
# 1:    A      3   A
# 2:    A      3   B
# 3:    A      3   C
# 4:    A      4   D
# 5:    A      6   E
# 6:    A      6   F
#...

Upvotes: 2

Ronak Shah
Ronak Shah

Reputation: 388982

You can use purrr's map_df :

result <- purrr::map_df(list, as.data.frame, .id = 'Name')
result

#   Name Var1 Freq
#1     A    A    3
#2     A    B    3
#3     A    C    3
#4     A    D    4
#5     A    E    6
#6     A    F    6
#7     A    G    6
#8     A    H    3
#9     A    I    8
#10    A    J    8
#11    B    A    3
#12    B    B    2
#13    B    D    1
#14    B    F    4
#15    B    G    5
#16    B    H    4
#17    B    I    1
#18    B    J    3
#19    B    K    3
#20    B    L    3
#21    B    M    4
#22    B    N    3
#23    B    O    1
#24    B    P    4
#25    B    Q    2
#26    B    R    2
#27    B    S    4
#28    B    T    1

Base R is bit more verbose but can be achieved as :

tmp <- lapply(list, as.data.frame)
do.call(rbind, Map(cbind, Name = names(tmp), tmp))

Upvotes: 4

Related Questions