在R中优化类sumif查询
我有一个180万行的数据框,每行包含30000个标记中的一个或多个。我试图找出有多少行包含每个标记的一个实例。有些项目包含多达25个标记,每个标记都位于其自己的列中。任何行都不包含任何标记的多个实例:在R中优化类sumif查询,r,sumifs,R,Sumifs,我有一个180万行的数据框,每行包含30000个标记中的一个或多个。我试图找出有多少行包含每个标记的一个实例。有些项目包含多达25个标记,每个标记都位于其自己的列中。任何行都不包含任何标记的多个实例: ItemNo <- c(1, 2, 3, 4) Tag1 <- c("ZZZ", "AAA", "BBB", "YYY") Tag2 <- c("YYY2", "ZZZ", "AAA", "XXX") Tag3 <- c("", "YYY2", "AAA2",
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
我能够使用for循环获得很好的结果,该循环大约需要3个小时来运行数据集:
for (i in 1:nrow(tags)) {tags[i,2] <- sum(Items[,2:7] ==
as.character(tags[i,1]), na.rm = TRUE)}
for(i in 1:nrow(tags)){tags[i,2]我无法在您的大数据集上测试速度,但我猜这会更快,因为它使用apply
而不是for
循环:
Sums <- data.frame(Code = Code,
COUNT = unlist(lapply(Code, function(i)
sum(apply(Items, 1, function(x) any(i %in% x))))))
让我们举一个与您的规模相近的例子:
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))
在笔记本电脑上运行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
请注意,它还计算空白-您可能希望在事后将其子集
编辑:为了提高速度,您可以使用制表
而不是制表
制表
有我们在这种情况下不需要的选项-制表
是精简版。使用制表
而不是制表
在我的计算机上运行不到10秒。制表(未列出(标签[-1])
。并在运行循环之前将所有列转换为character
。(或任何其他内容)。最好在创建数据帧(stringsAsFactors=F
)时执行此操作。只需将移动为.character()
Out of the loop可能会将您3小时的运行时间减少30分钟。使用table/unlist将运行时间从2小时55分钟减少到9秒。非常好,谢谢!这比我的for loop更优雅。有趣的是,它实际上将运行时间比我原来的增加了大约三倍。我想不出为什么会这样。一个是ason可能是我从“tags”中的列而不是原始数组中读取。此方法还有一个额外的好处,即恢复“tags”的原始顺序。很明显,我的方法没有帮助。对不起,我会删除答案,但我认为它可能提供信息,所以我将其保留。
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))
system.time(table(unlist(Items[-1])))
# user system elapsed
# 15.077 1.001 16.277
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