我使用stringdist()
合併相似的名字,並有工作用lapply
,但它採取11小時通過50萬行運行,我想看看data.table解決方案是否會更快。這裏有一個例子,我的嘗試性解決方案,到目前爲止,從讀數here,here,here,here,並且here建的,但我不是很拉斷:比較項目通過對所有列等行和環 - R的
library(stringdist)
library(data.table)
data("mtcars")
mtcars$cartype <- rownames(mtcars)
mtcars$id <- seq_len(nrow(mtcars))
我目前使用lapply()
循環通過cartype
列中的字符串,並將其名稱比指定值(.08)更接近的那些行彙集在一起。
output <- lapply(1:length(mtcars$cartype), function(x) mtcars[which(stringdist(mtcars$cartype[x], mtcars$cartype, method ="jw", p=0.08)<.08), ])
> output[1:3]
[[1]]
mpg cyl disp hp drat wt qsec vs am gear carb cartype id
Mazda RX4 21 6 160 110 3.9 2.620 16.46 0 1 4 4 Mazda RX4 1
Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4 Mazda RX4 Wag 2
[[2]]
mpg cyl disp hp drat wt qsec vs am gear carb cartype id
Mazda RX4 21 6 160 110 3.9 2.620 16.46 0 1 4 4 Mazda RX4 1
Mazda RX4 Wag 21 6 160 110 3.9 2.875 17.02 0 1 4 4 Mazda RX4 Wag 2
[[3]]
mpg cyl disp hp drat wt qsec vs am gear carb cartype id
Datsun 710 22.8 4 108 93 3.85 2.32 18.61 1 1 4 1 Datsun 710 3
數據表嘗試:
mtcarsdt <- as.data.table(mtcars)
myfun <- function(x) mtcars[which(stringdist(mtcars$cartype[x], mtcars$cartype, method ="jw", p=0.08)<.08), ]
的中間步驟:此代碼拉動基於行的值相似名稱的我手動插入myfun()
,但它重複對所有行該值。
res <- mtcarsdt[,.(vlist = list(myfun(1))),by=id]
res$vlist[[1]] #correctly combines the 2 mazda names
res$vlist[[6]] #but it's repeated down the line
我現在試圖循環使用所有行,使用set()
。我很接近,但儘管出現代碼從12列(cartype
)的文本被正確匹配是從第一列返回值,mpg
:
for (i in 1:32) set(mtcarsdt,i ,12L, myfun(i))
> mtcarsdt
mpg cyl disp hp drat wt qsec vs am gear carb cartype id
1: 21.0 6 160.0 110 3.90 2.620 16.46 0 1 4 4 c(21, 21) 1
2: 21.0 6 160.0 110 3.90 2.875 17.02 0 1 4 4 c(21, 21) 2
3: 22.8 4 108.0 93 3.85 2.320 18.61 1 1 4 1 22.8 3
現在,這是相當哈克,但我發現如果我創建cartype
列的副本並將其放置在第一列中,它幾乎可以工作,但必須有一個更簡潔的方法來執行此操作。此外,將輸出保持爲上述輸出的列表形式會很好,因爲我爲該格式設置了其他後處理步驟。
mtcars$cartypeorig <- mtcars$cartype
mtcars <- mtcars[,c(14,1:13)]
mtcarsdt <- as.data.table(mtcars)
for (i in 1:32) set(mtcarsdt,i ,13L, myfun(i))
> mtcarsdt[1:14,cartype]
[1] "c(\"Mazda RX4\", \"Mazda RX4 Wag\")"
[2] "c(\"Mazda RX4\", \"Mazda RX4 Wag\")"
[3] "Datsun 710"
[4] "Hornet 4 Drive"
[5] "Hornet Sportabout"
[6] "Valiant"
[7] "Duster 360"
[8] "c(\"Merc 240D\", \"Merc 230\", \"Merc 280\")"
[9] "c(\"Merc 240D\", \"Merc 230\", \"Merc 280\", \"Merc 280C\")"
[10] "c(\"Merc 240D\", \"Merc 230\", \"Merc 280\", \"Merc 280C\")"
[11] "c(\"Merc 230\", \"Merc 280\", \"Merc 280C\")"
[12] "c(\"Merc 450SE\", \"Merc 450SL\", \"Merc 450SLC\")"
[13] "c(\"Merc 450SE\", \"Merc 450SL\", \"Merc 450SLC\")"
[14] "c(\"Merc 450SE\", \"Merc 450SL\", \"Merc 450SLC\")"
我想避免距離矩陣方法(內存限制)和分割數據集。拆分它將在每個矩陣中起作用,但隨後識別多個矩陣中的匹配會帶來額外的挑戰。例如,假設2個名字在一個矩陣中匹配,另外2個名字在另一個匹配。在最終的數據集中將這4個相似的名稱組合在一起將會很有挑戰性。也有時候一個名字會匹配3個其他名字,但其他名字不會匹配原始名稱,這是我可以用原始方法處理的,但是對於多個矩陣會更難。 –