在R中优化类sumif查询

在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",

我有一个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", "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