从图中可以看出,我有一个包含订单号的列和一个包含物料编号的列。
我想找到一对材料以相同顺序出现的频率。
问题是我有30000行订单号和700个唯一的物料编号。它甚至可能吗?
我在想是否更容易制作一个包含行和列的700个材料编号的矩阵,并计算出现次数。
编辑:第一张照片不是一个好例子。我用随机材料编号上传了第二张图片。所以我希望它计算每一对(例如10-11,正如我突出显示的),出现在同一顺序中的次数。可以看出,10和11出现在3个不同的顺序中。答案 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)