R优化代码:查找最常见的项目集/替代产品

时间:2016-06-21 08:45:56

标签: r optimization

我有一个由两个变量组成的表: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,.)
})

我找到了一个(简单的四步)解决方案来解决我的问题:

  1. 我清理了我的数据(并删除了所有冗余信息。由于我对连接到特定pid的不同数量的cid感兴趣,我可以删除所有重复的行。

  2. 在查看我的数据之前,我将其缩减为相关行,而不是查看整个数据集(仅包含与我的source-pid相同的cid的行)。

  3. 由于替代品必须与source-pid不同,我可以删除引用source-pid的行。

  4. 使用干净的数据集我可以简单地计算每个pid的出现次数,直接引用带有source-pid的共享cid的数量。

  5. 我的原始代码花了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"))
    

1 个答案:

答案 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