我有一个包含180万行的数据帧,每行包含一个或多个30,000个标记。我正在尝试查找有多少行包含每个标记的实例。有些项目包含多达25个标签,每个标签都在自己的列中。没有行包含任何标记的多个实例:
ItemNo <- c(1, 2, 3, 4)
Tag1 <- c("ZZZ", "AAA", "BBB", "YYY")
Tag2 <- c("YYY2", "ZZZ", "AAA", "XXX")
Tag3 <- c("", "YYY2", "AAA2", "XXX3")
Tag4 <- c("", "", "", "AAA")
Tag5 <- c("", "", "", "ZZZ")
Tag6 <- c("", "", "", "YYY2")
Items <- data.frame(ItemNo, Tag1, Tag2, Tag3, Tag4, Tag5, Tag6)
Items
ItemNo Tag1 Tag2 Tag3 Tag4 Tag5 Tag6
1 1 ZZZ YYY2
2 2 AAA ZZZ YYY2
3 3 BBB AAA AAA2
4 4 YYY XXX XXX3 AAA ZZZ YYY2
标签世界位于一个单独的数据集中:
Code <- c("AAA", "BBB", "XXX", "ZZZ", "AAAA", "XXX3", "YYY2")
COUNT <- c(0, 0, 0, 0, 0, 0, 0)
tags <- data.frame(Code, COUNT)
tags
Code COUNT
1 AAA 0
2 BBB 0
3 XXX 0
4 ZZZ 0
5 AAAA 0
6 XXX3 0
7 YYY2 0
我想结束这样的事情:
Code COUNT
1 AAA 3
2 BBB 1
3 XXX 1
4 ZZZ 3
5 AAAA 0
6 XXX3 1
7 YYY2 3
我可以通过for循环获得良好的结果,这需要大约3个小时来运行数据集:
for (i in 1:nrow(tags)) {tags[i,2] <- sum(Items[,2:7] ==
as.character(tags[i,1]), na.rm = TRUE)}
是否有更有效或更优雅的方法来计算此数据集中每个标记的实例?
答案 0 :(得分:1)
让我们举一个与你的规模接近的例子:
n = 1e6
ncol = 25
ItemNo <- 1:n
tags = c("", do.call(paste0, expand.grid(LETTERS, LETTERS, LETTERS, stringsAsFactors = FALSE)))
item_tags = sample(tags, size = n * ncol, replace = T)
Items <- cbind.data.frame(ItemNo, matrix(item_tags, ncol = ncol))
上面有25个标记列,100万行,26 ^ 3 + 1 = 17577个唯一标记。
system.time(table(unlist(Items[-1])))
# user system elapsed
# 15.077 1.001 16.277
在除了第一列(未列出)之外的所有内容上运行table
,我的笔记本电脑上大约需要15秒。输出应该是可用的:
tt = table(unlist(Items[-1]))
head(tt)
# AAA AAB AAC AAD AAE
# 1421 1451 1456 1479 1440 1449
转换为数据框以匹配您想要的输出:
dd = data.frame(tt)
head(dd)
# Var1 Freq
# 1 1421
# 2 AAA 1451
# 3 AAB 1456
# 4 AAC 1479
# 5 AAD 1440
# 6 AAE 1449
请注意,它还会计算空白 - 您可能希望将这些空白分组。
修改:要获得更快的速度,您可以使用tabulate
而不是table
。 table
有我们在这种情况下不需要的选项 - tabulate
是一个精简版本。在我的计算机上使用tabulate
而不是table
在10秒内运行。
答案 1 :(得分:0)
我无法测试大数据集的速度,但我猜这会更快,因为它使用apply
代替for
循环:
Sums <- data.frame(Code = Code,
COUNT = unlist(lapply(Code, function(i)
sum(apply(Items, 1, function(x) any(i %in% x))))))
从COUNT =
行的中心开始,这种方法:
apply
来获得一个逻辑,指示可能代码的向量中的给定项是否出现在该行中。apply
的调用中调用lapply
,将该流程应用于代码矢量(Codes
)中的每个项目并对结果求和。结果:
> Sums
Code COUNT
1 AAA 3
2 BBB 1
3 XXX 1
4 ZZZ 3
5 AAAA 0
6 XXX3 1
7 YYY2 3