基于R中向量中每个列表的公共第一个元素组合列表向量中的所有元素

Combining all elements in a vector of lists based on the common first element of each list in the vector in R

我有一个相当大的列表向量(大约 300,000 行)。 例如,让我们考虑以下内容:

vec = c( 
  list(c("A",10,11,12)), 
  list(c("B",10,11,15)),
  list(c("A",10,12,12,16)),
  list(c("A",11,12,16,17)) )

现在,我想做以下事情:

对于向量中每个列表的每个唯一第一个元素,我需要向量中所有列表中与此对应的所有唯一元素,以及各自的频率。

输出有点像:

对于 A,我将分别拥有频率为 2,2,4,2 & 1 的元素 10, 11 12, 16 & 17。对于 B,它将是 10, 11, 15,频率为 1,1,1

非常感谢, 安库尔.

这是一种方法。

首先,创建列表的更简单方法是:

L <- list(c("A", 10, 11, 12), 
          c("B", 10, 11, 15), 
          c("A", 10, 12, 12, 16), 
          c("A", 11, 12, 16, 17))

现在您可以按第一个字符拆分,然后对除第一个字符以外的所有字符进行制表。

tapply(L, sapply(L, '[[', 1), function(x) 
  table(unlist(lapply(x, function(x) x[-1]))))

## $A
## 
## 10 11 12 16 17 
##  2  2  4  2  1 
## 
## $B
## 
## 10 11 15 
##  1  1  1 

扩展到包含 300,000 个相似大小元素的列表:

L <- replicate(300000, c(sample(LETTERS, 1), sample(100, sample(3:4, 1))))

system.time(
  freqs <- tapply(L, sapply(L, '[[', 1), function(x) 
    table(unlist(lapply(x, function(x) x[-1]))))
)

## user  system elapsed 
## 0.68    0.00    0.69 

如果你想对结果列表的向量进行排序,按照下面 OP 的评论,你可以只修改应用于 L:

组的函数
tapply(L, sapply(L, '[[', 1), function(x) 
  sort(table(unlist(lapply(x, function(x) x[-1]))), decreasing=TRUE))

## $A
## 
## 12 10 11 16 17 
##  4  2  2  2  1 
## 
## $B
## 
## 10 11 15 
##  1  1  1 

如果您只想将特定组的值制成表格,例如组 A(以 A 开头的向量),您可以对上述结果进行子集:

L2 <- tapply(L, sapply(L, '[[', 1), function(x) 
  sort(table(unlist(lapply(x, function(x) x[-1]))), decreasing=TRUE), 
  simplify=FALSE)

L2$A

(请注意,我添加了 simplify=FALSE,这样即使不同组中唯一元素的数量相同,它也能正常工作。)

只对感兴趣的组执行操作更有效,但在这种情况下,以下方法可能更好:

sort(table(unlist(
  lapply(split(L, sapply(L, '[[', 1))$A, function(x) x[-1])
)), decreasing=TRUE)

其中 split 首先根据向量的第一个元素将 L 分成组,然后我们将 A$A.[=24= 进行子集化]