按组计算数据中分数的有效方法

时间:2019-07-24 08:06:23

标签: r data.table

我有以下data.table,并且我希望按组(id)计算该组所有其他成员中最小(min)的jarowinkler分数。我正在寻找一个简单的嵌套循环,尽管它正在寻找一种更有效的方法。

library(data.table)
# install.packages("stringdist")
library(stringdist)

# Create `data.table`
dt <- data.table(id = c(1,1,2,2,2,3,3,3,3,4,4,4), 
                var = c("a","a","kyle","kyle","kile","rage","page","cage","","asd","fdd","xzx"))

# Add a numeric empty score variable         
dt[, "score" := as.numeric()]       
# Create a unique id within each group         
dt[, uid := sequence(.N), by = id]

dt
#     id  var score uid
#  1:  1    a    NA   1
#  2:  1    a    NA   2
#  3:  2 kyle    NA   1
#  4:  2 kyle    NA   2
#  5:  2 kile    NA   3
#  6:  3 rage    NA   1
#  7:  3 page    NA   2
#  8:  3 cage    NA   3
#  9:  3         NA   4
# 10:  4  asd    NA   1
# 11:  4  fdd    NA   2
# 12:  4  xzx    NA   3

当前的但缓慢的方法:

# Loop over all unique id's
for(i in unique(dt$id)){
   # Loop over each member and compute lowest stringdist 
   for(j in 1:nrow(dt[id == i])){
        dt[id == i & uid == j, "score" := min(stringdist(dt[id == i & uid == j, var], 
                                              dt[id == i & uid != j, var],
                                              method = "jw"))]
    }
}

dt[]
#     id  var     score uid
#  1:  1    a 0.0000000   1
#  2:  1    a 0.0000000   2
#  3:  2 kyle 0.0000000   1
#  4:  2 kyle 0.0000000   2
#  5:  2 kile 0.1666667   3
#  6:  3 rage 0.1666667   1
#  7:  3 page 0.1666667   2
#  8:  3 cage 0.1666667   3
#  9:  3      1.0000000   4
# 10:  4  asd 0.4444444   1
# 11:  4  fdd 0.4444444   2
# 12:  4  xzx 1.0000000   3

1 个答案:

答案 0 :(得分:2)

(再三考虑,这实际上与David的评论非常接近)一种可能的方法:

3000.00

动机:由于#create combinations of unique var by group then call stringdist once jw <- dt[, if (uniqueN(var)>1) transpose(combn(unique(var), 2, simplify=FALSE)), .(id)][, dis := stringdist(V1, V2, "jw")] #find the min distance for each word lu <- rbindlist(list(jw[, .(mdis=min(dis)), .(id, var=V1)], jw[, .(mdis=min(dis)), .(id, var=V2)])) #update join on the min distance for each word dt[lu, on=.(var, id), score := mdis] #for duplicated words, dist is 0 dt[dt[, .I[duplicated(var) | duplicated(var, fromLast=TRUE)], by=.(id)]$V1, score := 0] 已经为提高速度而构建,并且通过使用'openMP'(从手册中)并行运行,因此如果一次运行stringdist而不是按组多次运行,它将更快。