对R中的大数据进行有效的字符串匹配(和索引编制)的技巧?

我想做什么

我有许多唯一的ID,例如id1,id2,etc.。它们出现在多个组中,每个组都是1到100个ID之间的随机样本,例如

[1] "id872- id103- id746-"                             
[2] "id830- id582-"                                   
[3] "id663- id403- id675- id584- id866- id399- id28- id550-"

我想找到一个ID所属的所有组,例如为id1

groups.with.id[1] = grep("id1-",groups)

我的问题

数据很大(8万个ID,100万个群组),这在我的笔记本电脑上大约需要 12小时。我认为这是以下事实的组合:我做了80k次(每个id一次),并且每次我访问一个巨大的对象(1M组)。

有什么方法可以提高效率?

(我经常在R中遇到较大的对象的问题。例如,重复索引具有1万行以上的数据帧会很快变慢。对大型对象进行有效索引的一般答案也很受欢迎!

示例代码

# make toy dataset
n.ids = 80000 # number of unique ids
n.groups = 100 # number of groupings

# make data
ids = paste("id",1:n.ids,"-",sep="")
groups = character(n.groups)
for (ii in 1:n.groups) {
  group.size = ceiling(runif(1) * 10)
  groups[ii] = paste(sample(ids,group.size),collapse=" ")
}

# execute and time
t1 = Sys.time()
groups.with.id = sapply(ids,grep,groups)
difftime(Sys.time(),t1)

> Time difference of 29.63272 secs

在此示例中,500个组耗时约30秒。我想扩大到100万个小组。有有效的方法吗?

ad3867 回答:对R中的大数据进行有效的字符串匹配(和索引编制)的技巧?

这里是tidyverse的替代方案。一个可能的缺点是,数据中不存在的ID将不会包含在输出中-尽管可以在必要时解决此问题。

library(tidyverse)

groups.with.id <- groups %>% 
  enframe() %>%
  separate_rows(value,sep = " ") %>%
  group_by(value) %>%
  summarise(ids = list(name)) %>%
  mutate(ids = set_names(ids,value)) %>%
  pull(ids)

如果您还想知道在任何组中不存在哪些ID,可以使用:

setdiff(ids,names(groups.with.id))

基准测试表明,此方法在示例数据集上的速度比将grepfixed = TRUE结合使用要快100倍以上。

microbenchmark::microbenchmark(original = sapply(ids,grep,groups),original_fixed = sapply(ids,groups,fixed = TRUE),separate_summarise_groups = {groups %>% 
                                   enframe() %>%
                                   separate_rows(value,sep = " ") %>%
                                   group_by(value) %>%
                                   summarise(ids = list(name)) %>%
                                   mutate(ids = set_names(ids,value)) %>%
                                   pull(ids)},times = 10,unit = "relative")

Unit: relative
                      expr      min       lq     mean   median        uq       max neval cld
                  original 685.0922 695.7236 382.0759 641.2018 290.30233 188.40790    10   c
            original_fixed 199.8912 209.1225 115.5693 199.9749  85.89842  59.26886    10  b 
 separate_summarise_groups   1.0000   1.0000   1.0000   1.0000   1.00000   1.00000    10 a 
本文链接:https://www.f2er.com/2990019.html

大家都在问