每个观察我有3个离散属性 . 如果对于2个观察值,这些属性中至少有2个采用相同的值,那么我想将它们组合在一起(实际上总是最多2个属性是相同的) .
我的想法是 Build 一个分组矩阵 . 每行和每列代表一个观察 . 行和列的交叉表示两个观测值的"similarity",如果至少两个属性值相同,则应采用值 TRUE
,否则为 FALSE
.
这是我所做的可重复的示例( a
, b
, c
是要比较的属性):
df <- data.frame(a = c(1, 1, 2, 2, 3),
b = c(1, 2, 3, 2, 4),
c =c("a", "a", "d", "a", "c"))
grouping_matrix <- matrix(nrow = nrow(df), ncol = nrow(df))
for (i in 1:nrow(df)){
for (j in 1:nrow(df)){
if(sum(df[i, ] == df[j, ]) >= 2) {
grouping_matrix [i, j] <- TRUE
} else {
grouping_matrix [i, j] <- FALSE
}
}
}
> df
a b c
1 1 1 a
2 1 2 a
3 2 3 d
4 2 2 a
5 3 4 c
> grouping_matrix
[,1] [,2] [,3] [,4] [,5]
[1,] TRUE TRUE FALSE FALSE FALSE
[2,] TRUE TRUE FALSE TRUE FALSE
[3,] FALSE FALSE TRUE FALSE FALSE
[4,] FALSE TRUE FALSE TRUE FALSE
[5,] FALSE FALSE FALSE FALSE TRUE
这很有效 . 然而,即使对于一些thousend观察,它也需要永远 . 我很确定有一些更有效的方式,例如一些 data.table
魔法 . 如果问题没有明确说明,请告诉我 .
3 回答
如果您遇到性能问题 avoid matrixes . 任何需要距离矩阵的东西都需要至少O(n²)的时间,并且需要永远 . 在R中,因为R解释器非常慢,所以避免任何for循环 . 像所有快速R模块一样,用C或Fortran重写代码 . 纯R是sloooow .
但是你的方法有一个更普遍的问题 . 如果a和b应该分组,b和c应该分组,但a和c太不同了怎么办?例如
a和b共有X Y,b和c共有Y和Z,但a和c只有Y.
如果可以对a和c进行分组,那么您正在寻找 transitive closure . disjoint set structure 可以帮助加速这种计算 .
没有双
for
循环,这样做也是如此 . 我会做一个快速的性能测试来检查它是否相当快 .或者,这可以通过重塑和自联接来解决 . 此方法不会将每一行相互比较(如嵌套的
for
循环或嵌套的lapply()
方法),而只是查找列名和值中的匹配项 .解释
首先,通过将所有列从宽格式转换为长格式(在添加行id
rn
之后)创建临时data.tablemDT
.然后,
mDT
与列的名称和值自身连接:参数
nomatch = 0L
试图减少结果行数,因为OP已报告其 生产环境 数据集存在问题 .现在,对于
rn
和i.rn
的每个组合计算匹配数,并检查该数字是否大于1:最后,根据要求将该结果重新整形为类似矩阵的结构 .