我有一個大型數據集tPro1
(〜500k points)。如下所示,感興趣的變量是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
,一對夫婦十幾dataponts的。它具有比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。之後它們被移除/跳過以節省無意義的重新檢查時間。- 路徑s可能在
tPro1
中出現多次。因此,當爲s發現有效的子字符串p時,算法會遍歷數據集並查找s的所有未經檢查的實例,而不是繼續執行grepl。
- 路徑s可能在
我的代碼是
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
)需要46secs。 2000需要1分鐘,3000:1.4分鐘。
可以做出什麼顯着的改進,還是僅僅是問題的本質?
編輯:大約有54K獨特長的路徑,並且還不是所有的長路徑的具有對應的短路徑(例如在tPro1
有>root>strange>path
,而在sub1
沒有形式>root>strange
的路徑)
編輯2:在下面的rosscova的回答下,時間從可能的永恆性下降到279.75秒!
你也可以發送一些數據(如鏈接或不適用?) – amonk
字符串'> root> aaaa> bbbb> cccc> dddd> hello'的總數是否與'>'相同。我的意思是你可以有嗎? '> root> aaaa> bbbb> cccc> dddd> xxxx>ΖΖΖΖ> hello' – amonk
不幸的是,我正在使用的數據無法公開,這使我知道重複性令人感到尷尬。字符串有一個可變數字>'s –