sds
sds

Reputation: 60064

combine tables into a data frame

How do I turn a list of tables into a data frame?

I have:

> (tabs <- list(table(c('a','a','b')),table(c('c','c','b')),table(c()),table(c('b','b'))))
[[1]]

a b 
2 1 

[[2]]

b c 
1 2 

[[3]]
< table of extent 0 >

[[4]]

b 
2 

I want:

> data.frame(a=c(2,0,0),b=c(1,1,2),c=c(0,2,0))
  a b c
1 2 1 0
2 0 1 2
3 0 0 0 
4 0 2 0 

PS. Please do not assume that the tables were created by table calls! They were not!

Upvotes: 1

Views: 706

Answers (4)

A5C1D2H2I1M1N2O1R2T1
A5C1D2H2I1M1N2O1R2T1

Reputation: 193677

Here is a pretty clean approach:

library(reshape2)
newTabs <- melt(tabs)
newTabs
#   Var1 value L1
# 1    a     2  1
# 2    b     1  1
# 3    b     1  2
# 4    c     2  2
# 5    b     2  4

newTabs$L1 <- factor(newTabs$L1, seq_along(tabs))
dcast(newTabs, L1 ~ Var1, fill = 0, drop = FALSE)
#   L1 a b c
# 1  1 2 1 0
# 2  2 0 1 2
# 3  3 0 0 0
# 4  4 0 2 0

This makes use of the fact that there is a melt method for lists (see reshape2:::melt.list) which automatically adds in a variable (L1 for an unnested list) that identifies the index of the list element. Since your list has some items which are empty, they won't show up in your melted list, so you need to factor the "L1" column, specifying the levels you want. dcast takes care of restructuring your output and allows you to specify the desired fill value.

Upvotes: 0

matt_k
matt_k

Reputation: 4489

c_names <- unique(unlist(sapply(tabs, names)))
df <- do.call(rbind, lapply(tabs, `[`, c_names))
colnames(df) <- c_names
df[is.na(df)]  <- 0

Upvotes: 2

rawr
rawr

Reputation: 20811

tabs <- list(table(c('a','a','b')),table(c('c','c','b')),table(c()),table(c('b','b')))


dat.names <- unique(unlist(sapply(tabs, names)))


dat <- matrix(0, nrow = length(tabs), ncol = length(dat.names))
colnames(dat) <- dat.names


for (ii in 1:length(tabs)) {
   dat[ii, ] <- tabs[[ii]][match(colnames(dat), names(tabs[[ii]]) )]
}

dat[is.na(dat)] <- 0

> dat
     a b c
[1,] 2 1 0
[2,] 0 1 2
[3,] 0 0 0
[4,] 0 2 0

Upvotes: 2

BrodieG
BrodieG

Reputation: 52687

This assumes the tables are one dimensional.

all.names <- unique(unlist(lapply(tabs, names)))
df <- as.data.frame(do.call(rbind, 
  lapply(
    tabs, function(x) as.list(replace(c(x)[all.names], is.na(c(x)[all.names]), 0))
) ) )    
names(df) <- all.names
df

There is probably a cleaner way to do this.

#   a b c
# 1 2 1 0
# 2 0 1 2
# 3 0 0 0
# 4 0 2 0

Upvotes: 2

Related Questions