基于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= 进行子集化]
我有一个相当大的列表向量(大约 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= 进行子集化]