我有一个由两个变量组成的表:product-id和customer-id。这两个变量的任何组合都可以多次出现(cid' d'可以链接到pid' 3'不止一次)。我想要实现的是为data.table中的每个pid识别替代pid。那么,看看pid =' 5'我可以识别三种不同的cid(a,c,d)。在我的下一步中,我正在寻找与pid =' 5'共享多个cid的pid(s)。尽可能。在这种情况下,我正在寻找的pid是' 10'它与pid' 5相同的cid(a,c,d)相关联。
下面的一段代码适用于小型表,但是当我在一个大型表(3.000 pids,900.000 cids,4.000.000行)上运行时,它会永远存在。所以我正在寻找一种优化代码的方法(或用更好的代码替换它)。
# load packages
library(data.table)
library(magrittr)
# create data.table
set.seed(123)
dt <- data.table(cbind(sample(1:10,20,replace=T),sample(c("a","b","c","d"),20,replace=T)))
colnames(dt) <- c("pid", "cid")
# find substitutes
sub <- lapply(unique(dt$pid), function(f) {
dt[,list(cid_freq=sum(unique(cid) %in% unique(dt$cid[dt$pid==f]))),by=pid] %>%
subset(pid!=f,select=c("pid","cid_freq")) %>%
setkey() %>%
unique() %>%
.[order(-cid_freq)[1],] %>%
cbind(f,.)
})
我找到了一个(简单的四步)解决方案来解决我的问题:
我清理了我的数据(并删除了所有冗余信息。由于我对连接到特定pid的不同数量的cid感兴趣,我可以删除所有重复的行。
在查看我的数据之前,我将其缩减为相关行,而不是查看整个数据集(仅包含与我的source-pid相同的cid的行)。
由于替代品必须与source-pid不同,我可以删除引用source-pid的行。
使用干净的数据集我可以简单地计算每个pid的出现次数,直接引用带有source-pid的共享cid的数量。
我的原始代码花了8个多小时(此时我取消了操作),使用新代码可以将执行时间减少到13分钟。
# create data.table
set.seed(123)
dt <- data.table(cbind(sample(1:3000,4000000,replace=T),sample(1:900000,4000000,replace=T)))
colnames(dt) <- c("pid", "cid")
# find substitutes
sub <- lapply(unique(dmmy$pid),function(f){
filter <- (dmmy$cid %in% dmmy$cid[dmmy$pid==f])&(dmmy$pid!=f)
dmmy[filter] %>%
.[,list(KDN_ANZ=.N),by=pid] %>%
setorder(-KDN_ANZ) %>%
.[1] %>%
set_colnames(c("sub_pid","sub_cid")) %>%
cbind(f)
})
sub <- data.table(matrix(unlist(sub),ncol=3,byrow=T)) %>%
set_colnames(c("sub_pid","sub_cid","pid"))
答案 0 :(得分:0)
您是否尝试过使用距离矩阵?
dt2 <- dcast(dt, pid~cid)
m <- as.matrix(dt2[,-1,with=F])
rownames(m) <- dt2$pid
d <- dist(m, meth="bin")
as.matrix(d)[, "5"]
# 1 10 2 3 4 5 6 7 8 9
# 0.3333333 0.0000000 0.6666667 0.6666667 1.0000000 0.0000000 0.5000000 0.6666667 0.6666667 0.5000000
在这种情况下,10
的最大相似度/最小距离为0
。