计算具有两个给定值的变量的出现次数,该值对应于另一个变量

时间:2018-05-23 07:56:49

标签: r matrix count

从图中可以看出,我有一个包含订单号的列和一个包含物料编号的列。

我想找到一对材料以相同顺序出现的频率。

问题是我有30000行订单号和700个唯一的物料编号。它甚至可能吗?

我在想是否更容易制作一个包含行和列的700个材料编号的矩阵,并计算出现次数。

PICTURE

编辑:第一张照片不是一个好例子。我用随机材料编号上传了第二张图片。所以我希望它计算每一对(例如10-11,正如我突出显示的),出现在同一顺序中的次数。可以看出,10和11出现在3个不同的顺序中。

PICTURE2

2 个答案:

答案 0 :(得分:0)

就存储空间而言,最佳解决方案是每对一行,即700 * 699 / 2.这个问题仍然相对较小,操纵700 * 700矩阵的简单性可能比700更有价值*你要保存的701/2个单元,每个单元一个字节可以达到240kB。如果矩阵是稀疏的(即大多数材料对从不一起排序),并且你使用适当的数据结构,它可能会更少。

以下是代码的外观:

首先,我们要创建一个包含与材料一样多的行和列的数据框。矩阵更容易创建,因此我们创建一个我们之后转换为数据帧的矩阵。

all_materials = levels(as.factor(X$Materials))
number_materials = length(all_materials)
Pairs <- as.data.frame(matrix(data = 0, nrow = number_materials, ncol = number_materials))

(这里,X是您的数据集)

然后我们设置行名称和列名称,以便能够直接使用材料的标识符访问行和列,这些标识符显然不一定从1到700编号。

colnames(Pairs) <- all_materials
rownames(Pairs) <- all_materials

然后我们迭代数据集

for(order in levels(as.factor(X$Order.number))){
  # getting the materials in each order
  materials_for_order = X[X$Order.number==order, "Materials"]
  if (length(materials_for_order)>1) {
    # finding each possible pair from the materials list
    all_pairs_in_order = combn(x=materials_for_order, m=2)
    # incrementing the cell at the line and column corresponding to each pair
    for(i in 1:ncol(all_pairs_in_order)){
      Pairs[all_pairs_in_order[1, i], all_pairs_in_order[2, i]] = Pairs[all_pairs_in_order[1, i], all_pairs_in_order[2, i]] + 1
    }
  }
}

在循环结束时,Pairs表应包含您需要的所有内容。

答案 1 :(得分:0)

这是data.table解决方案

library(data.table)    
combis <- data.table(do.call(rbind, 
    DT[, if (.N > 1) list(combn(Materials, 2, simplify=FALSE)), by=Order.number]$V1
))
ans <- combis[, .N, by=.(V1, V2)]

#check results
setorder(ans, V1, V2)
ans

一个base方法:

allComb <- by(DT, DT$Order.number, function(x) {
    if (nrow(x) > 1) {
        return(combn(x$Materials, 2, simplify=FALSE)))
    }
    NULL
}
materialsPairs <- as.data.frame(do.call(rbind, unlist(allComb, recursive=FALSE)))

#https://stackoverflow.com/a/18201245/1989480
res <- aggregate(cnt ~ ., data=transform(materialsPairs, cnt=1), length)

#check results
head(res[order(res$V1, res$V2),])

数据:

library(data.table)
set.seed(0L)
M <- 30e3
nOrd <- 3000
DT <- data.table(Order.number=sample(nOrd, M, replace=TRUE), 
    Materials=sample(700, M, replace=TRUE))
setorder(DT, Order.number, Materials)