test
我正在寻找一种实现,该实现确定一个(例如)数据帧中的所有记录到第二个(例如)数据帧中的任何记录的 Gower 距离的最小值training
。结果是一个向量,其中的每一行都有一个元素test
。
数据是具有无序分类属性的分类数据,并且可以生成,例如,如下所示:
set.seed(20130926L)
DIMS <- 12
CATS <- 2
create.data <- function(SPARSITY) {
sparse.data <- rbinom(CATS ** DIMS, 1, SPARSITY)
sparse.array <- array(sparse.data, dim=rep(CATS, DIMS))
sparse.table <- as.table(sparse.array)
sparse.df <- as.data.frame(sparse.table)
sparse.df <- subset(sparse.df, Freq > 0, select=-Freq)
sparse.df
}
data.train <- create.data(0.001)
data.test <- create.data(0.01)
head(data.train, 3)
## Var1 Var2 Var3 Var4 Var5 Var6 Var7 Var8 Var9 Var10 Var11 Var12
## 745 A A A B A B B B A B A A
## 1156 B B A A A A A B A A B A
## 1574 B A B A A B A A A B B A
summary(data.test)
## Var1 Var2 Var3 Var4 Var5 Var6 Var7 Var8 Var9 Var10
## A:24 A:31 A:23 A:20 A:30 A:27 A:22 A:20 A:26 A:23
## B:24 B:17 B:25 B:28 B:18 B:21 B:26 B:28 B:22 B:25
## Var11 Var12
## A:24 A:22
## B:24 B:26
data.test
对于 中的所有行,我如何找到data.training
高尔距离最小的行(或者至少是到该特定行的距离)?下面的代码有效,但对于 20 个属性或超过 2 个类别已经需要太多内存:
nrow(data.test)
## [1] 48
library(StatMatch, quietly=T, warn.conflicts=F)
apply(gower.dist(data.train, data.test), 2, min)
## [1] 0.3333 0.4167 0.2500 0.5000 0.3333 0.4167 0.2500 0.3333 0.2500 0.4167
## [11] 0.5000 0.3333 0.3333 0.3333 0.4167 0.4167 0.2500 0.4167 0.1667 0.3333
## [21] 0.4167 0.3333 0.4167 0.5000 0.3333 0.5000 0.5000 0.4167 0.3333 0.3333
## [31] 0.2500 0.4167 0.5000 0.4167 0.3333 0.5000 0.3333 0.4167 0.3333 0.3333
## [41] 0.5000 0.5833 0.5000 0.2500 0.3333 0.4167 0.3333 0.5000
该函数cluster::daisy()
还返回一个距离矩阵。
类似:如何计算大数据帧的欧几里得距离(并仅保存摘要)。在那里,建议对 的子集多次调用距离函数data.train
。我可以做到这一点,但计算时间仍然令人望而却步。
毕竟,高尔距离的定义允许更有效的算法,也许是递归的分治法,逐个属性地操作属性并在子集上调用自身。回想一下,Gower 的距离是属性距离的(加权)总和,定义为
- 对于分类属性:如果相等则为 0,否则为 1
- 对于有序属性:如果相等,则为 0,否则与排名距离成正比
- 对于连续属性(此处不需要):与属性的距离和范围的比率成正比
下面是一个简单的演示,其中计算了 和 的所有组合之间的高尔(A, A)
距离。一个属性不同的行的距离为 0.5,两个属性不同的行的最大距离为 1.0:A
B
(ex.train <- expand.grid(Var1=LETTERS[1:2], Var2=LETTERS[1:2]))
## Var1 Var2
## 1 A A
## 2 B A
## 3 A B
## 4 B B
ex.test <- ex.train[1, ]
gower.dist(ex.train, ex.test)
## [,1]
## [1,] 0.0
## [2,] 0.5
## [3,] 0.5
## [4,] 1.0
如果两者train.data
和test.data
都按列进行分析,可能的实现可能如下所示:
v
对于第一列的 所有值级别- 选择
test.data
第一列具有价值的子集v
- 选择
train.data
第一列具有价值的子集v
- 递归调用过程以获得最小值的上限
- 选择
train.data
第一列具有价值的子集<> v
- 使用先前获得的早期截止上限递归调用过程
- 选择
是否真的没有实现,或者可能有描述这种算法的论文?