【发布时间】:2017-12-02 23:05:04
【问题描述】:
我有一个大型数据集tPro1(约 500k 点)。如下所示,感兴趣的变量是tPro1$Path。
Path Row rm
1 >root>aaaa>bbbb>cccc>dddd>hello 1 TRUE
2 >root>aaaa>bbbb>cccc>dddd>greetings 2 TRUE
3 >root>aaaa>bbbb>cccc>dddd>example 3 TRUE
4 >root>iiii>jjjj>kkkk>llll>mmmm 4 TRUE
5 >root>iiii>jjjj>kkkk>nnnn>testing 5 TRUE
我还有一个较小的数据集,我们称之为Sub1,有几十个左右的数据点。它具有比tPro1 更高级别的路径。
[1] ">root>aaaa>bbbb>cccc>dddd"
[2] ">root>aaaa>bbbb>eeee>ffff"
[3] ">root>aaaa>bbbb>gggg>hhhh"
[4] ">root>iiii>jjjj>kkkk>llll>mmmm"
[5] ">root>iiii>jjjj>kkkk>nnnn"
[6] ">root>oooo>pppp>qqqq"
我要做的是将tPro1 中较长的路径与Sub1 中的较短路径相关联。 tPro1 是来自Pro0 的一些关键信息的副本。输出Pro0 将是
Path Short_path
1 >root>aaaa>bbbb>cccc>dddd>hello >root>aaaa>bbbb>cccc>dddd
2 >root>aaaa>bbbb>cccc>dddd>greetings >root>aaaa>bbbb>cccc>dddd
3 >root>aaaa>bbbb>cccc>dddd>example >root>aaaa>bbbb>cccc>dddd
4 >root>iiii>jjjj>kkkk>llll>mmmm >root>iiii>jjjj>kkkk>llll>mmmm
5 >root>iiii>jjjj>kkkk>nnnn>testing >root>iiii>jjjj>kkkk>nnnn
我已经为Sub1 中的每个路径编写了一个循环,grepl 的每个tPro1 以查看它是否是子字符串。对于 500k*24 点,这将是一个非常低效的过程,所以我尝试了一些优化:
- 注意
tPro1$rm。找到子字符串时,将其设置为 false。之后将它们删除/跳过以节省毫无意义的重新检查时间。- 一个 Path 可能在
tPro1中出现多次。因此,当找到 s 的有效子字符串 p 时,算法不会继续 grepl,而是遍历数据集并查找 s 的所有未检查实例。
- 一个 Path 可能在
我的代码是
start.time <- Sys.time()
for (p in Sub1$Path) {
for (i in 1:NROW(tPro1)) {
if (tPro1[i,3]) {
if (grepl(p, tPro1[i,1], fixed=TRUE)) {
# Replace all of subpath
for (j in i:NROW(tPro1)) {
if (tPro1[j,1] == tPro1[i,1]) {
Pro0[tPro1[j,2],2] <- p
tPro1[j,3] <- FALSE
}
}
}
}
}
v <- unlist(tPro1[,3])
tPro1 <- tPro1[v,]
}
end.time <- Sys.time()
time.taken <- end.time - start.time
time.taken
处理完整的数据集不会在人工时间内停止(至少在我的机器上)。出于说明目的,一次执行 1000 个批次(减少 tPro1)需要 46 秒。 2000 需要 1 分钟,3000:1.4 分钟。
可以进行任何明显的改进,还是仅仅是问题的本质?
编辑:大约有 54k 条独特的长路径,而且并非所有长路径都有相应的短路径(例如,在 tPro1 中有 >root>strange>path,而在 sub1 中没有路径形式>root>strange)
EDIT2:在下面rosscova 的回答之后,时间从可能永恒缩短到 279.75 秒!
【问题讨论】:
-
你也可以发送一些数据吗(比如链接或smth?)
-
字符串
>root>aaaa>bbbb>cccc>dddd>hello是否总是相同数量的>。我的意思是你能吃吗?>root>aaaa>bbbb>cccc>dddd>xxxx>ΖΖΖΖΖ>hello -
不幸的是,我正在使用的数据无法公开,这使得我知道的可重复性变得很尴尬。字符串有可变数量的 >'s
-
酷!所以让我知道一件事。你只需要知道大表是否包含小表的字符串,对吗?
-
是的,我也看不到循环的用途...将其转换为 data.table.. 并使用类似 DT[,shortPath := gsub("(^.*> )","\\1",路径)]。然后检查这个短路径是否出现在你的短路径表中......因此将它与那个合并
标签: r regex optimization substring grepl