2014-09-03 42 views
1

我有不同列表中的项目,我想计算每个列表中的项目并将其输出到表格。然而,当列表中有不同的项目时,我遇到了困难。也说明我的问题:与不同元素组合表

item_1 <- c("A","A","B") 
item_2 <- c("A","B","B","B","C") 
item_3 <- c("C","A") 
item_4 <- c("D","A", "A") 
item_5 <- c("B","D") 


list_1 <- list(item_1, item_2, item_3) 
list_2 <- list(item_4, item_5) 

table_1 <- table(unlist(list_1)) 
table_2 <- table(unlist(list_2)) 

> table_1 

A B C 
4 4 2 
> table_2 

A B D 
2 1 2 

我从cbind得到的是:

> cbind(table_1, table_2) 

    table_1 table_2 
A  4  2 
B  4  1 
C  2  2 

这显然是错误的。我需要的是:提前

table_1 table_2 
A  4  2 
B  4  1 
C  2  0 
D  0  2 

感谢

+0

你可以使你的角色向量因素(包括所有可能的值的级别)。 – Roland 2014-09-03 08:19:31

回答

3

它可能会更好,在一开始尽可能使用factors,像:

L <- list(list_1 = list_1, 
      list_2 = list_2) 
RN <- unique(unlist(L)) 
do.call(cbind, 
     lapply(L, function(x) 
      table(factor(unlist(x), RN)))) 
# list_1 list_2 
# A  4  2 
# B  4  1 
# C  2  0 
# D  0  2 

然而,你有什么打算,像下面可能在功能有用。我添加了评论来帮助解释每一步中发生的事情。

myFun <- function(..., fill = 0) { 
    ## Get the names of the ...s. These will be our column names 
    CN <- sapply(substitute(list(...))[-1], deparse) 
    ## Put the ...s into a list 
    Lst <- setNames(list(...), CN) 
    ## Get the relevant row names 
    RN <- unique(unlist(lapply(Lst, names), use.names = FALSE)) 
    ## Create an empty matrix. `fill` can be anything--it's set to 0 
    M <- matrix(fill, length(RN), length(CN), 
       dimnames = list(RN, CN)) 
    ## Use match to identify the correct row to fill in 
    Row <- lapply(Lst, function(x) match(names(x), RN)) 
    ## use matrix indexing to fill in the unlisted values of Lst 
    M[cbind(unlist(Row), 
      rep(seq_along(Lst), vapply(Row, length, 1L)))] <- 
    unlist(Lst, use.names = FALSE) 
    ## Return your matrix 
    M 
} 

应用到你的两个表,结果是这样的:

myFun(table_1, table_2) 
# table_1 table_2 
# A  4  2 
# B  4  1 
# C  2  0 
# D  0  2 

下面是与添加另一个table到问题的例子。它还演示了使用NA作为fill的值。

set.seed(1) ## So you can get the same results as me 
table_3 <- table(sample(LETTERS[3:6], 20, TRUE)) 
table_3 
# 
# C D E F 
# 2 7 9 2 

myFun(table_1, table_2, table_3, fill = NA) 
# table_1 table_2 table_3 
# A  4  2  NA 
# B  4  1  NA 
# C  2  NA  2 
# D  NA  2  7 
# E  NA  NA  9 
# F  NA  NA  2 
+0

这是一个功能先生的地狱 – 2014-09-03 08:48:30

+0

@DavidArenburg,怎么样?这很简单 - 只是有很多评论... – A5C1D2H2I1M1N2O1R2T1 2014-09-03 09:05:00

+0

不知道,它看起来很复杂,没有评论。但我会承认,它已经完全优化,每一行都是必要的 – 2014-09-03 09:06:42

0

快速解决你的问题是使表到数据帧,然后将它们合并:

d1 <- data.frame(value=names(table_1), table_1=as.numeric(table_1)) 
    d2 <- data.frame(value=names(table_2), table_2=as.numeric(table_2)) 
    merge(d1,d2, all=TRUE) 

这将创建NA的地方你可能需要0。这可以固定

M <- merge(d1,d2, all=TRUE) 
    M[is.na(M)] <- 0 
1

要解决现有的问题,你可以把两个表到一个列表并添加缺少的值的名字早在这里,nm是唯一的每个表的表名的向量,tbs是我们可以使用sapply来追加和重新排序缺失的值。

> nm <- unique(unlist(mget(paste("item", 1:5, sep = "_")))) 
> tbs <- list(t1 = table_1, t2 = table_2) 
> sapply(tbs, function(x) { 
     x[4] <- 0L 
     names(x)[4] <- nm[!nm %in% names(x)] 
     x[nm] 
    }) 
    t1 t2 
A 4 2 
B 4 1 
C 2 0 
D 0 2 

的一般解,因为当你有未知数,所以,你可以保持NA值,是

> sapply(tbs, function(x) { 
     length(x) <- length(nm) 
     x <- x[match(nm, names(x))] 
     setNames(x, nm) 
    }) 
    t1 t2 
A 4 2 
B 4 1 
C 2 NA 
D NA 2 

但您可以通过直行从itemstable完全避免这一点。您将这些项目放入列表中,然后在下一步中将其列出。 table中有一个useNA参数,即使它们为零,也会保持因子水平。

> t1 <- table(c(item_1, item_2, item_3), useNA = "always") 
> t2 <- table(c(item_4, item_5), useNA = "always") 
> table(c(item_4, item_5), useNA = "always") 

    A B D <NA> 
    2 1 2 0 
+0

虽然这不是很容易扩展。如果第二个表在我的回答中与“table_3”类似,该怎么办? – A5C1D2H2I1M1N2O1R2T1 2014-09-03 10:10:08

+0

我甚至在你的答案中找不到'table_3'。问题发生在第1步,我只是在说明如何避免它。你有没有注意到OP去了vector> list> unlist> table> cbind?表矢量和它完成。 – 2014-09-03 10:15:37

+0

“table_3”即将结束我的回答,以演示该功能的更多功能。例如,如果“item_5”是“c”(“B”,“D”,“X”)'',你会如何扩展你的答案? – A5C1D2H2I1M1N2O1R2T1 2014-09-03 10:23:33