proxy
может работать со списками матриц в качестве входных данных, вам нужно только определить функцию-оболочку, которая делает то, что вы хотите:
nested_gower <- function(x, y, ...) {
mean(proxy::dist(x, y, ..., method = "gower"))
}
proxy::pr_DB$set_entry(
FUN = nested_gower,
names = c("ngower"),
distance = TRUE,
loop = TRUE
)
df_list <- list(df1, df2, df3)
proxy::dist(df_list, df_list, method = "ngower")
[,1] [,2] [,3]
[1,] 0.1978306 0.2139304 0.8315169
[2,] 0.2139304 0.2245903 0.8320911
[3,] 0.8315169 0.8320911 0.2139049
Это все равно будет медленным, но должно быть быстрее, чемfor
петли в простой R (proxy
использует C на заднем плане).
Важно : обратите внимание, что диагональ полученной матрицы пересечения не имеет нулей.Если вы должны были позвонить dist
, как proxy::dist(df_list, method = "ngower")
, proxy
будет предполагать, что distance(x, y) = distance(y, x)
(симметрия), и что distance(x, x) = 0
, последнее из которых неверно в этом случае.Передача двух аргументов dist
предотвращает это предположение.Если вы действительно не заботитесь о диагонали, передайте только один аргумент, чтобы сэкономить дополнительное время, избегая вычислений в верхней треугольнике.В качестве альтернативы, если вы заботитесь о диагонали, но все же хотите избежать вычисления верхней треугольники, сначала вызовите dist
с одним аргументом, а затем вызовите proxy::dist(df_list, df_list, method = "ngower", pairwise = TRUE)
.
Примечание: если вы хотите имитировать это поведениес пакетом gower
(как предлагает db) вы можете определить функцию-обертку следующим образом:
nested_gower <- function(x, y, ...) {
distmat <- sapply(seq_len(nrow(y)), function(y_row) {
gower::gower_dist(x, y[y_row, , drop = FALSE], ...)
})
mean(distmat)
}
Однако возвращаемые значения, похоже, меняются в зависимости от того, сколько записей передано в функции, поэтомуТрудно сказать, какой подход был бы наилучшим.
* Сначала используйте proxy::pr_DB$delete_entry("ngower")
, если вы хотите переопределить функцию в proxy
.
Если вы предпочитаете proxy
В версии матрицы расстояний Gower мне кажется, что вы можете использовать некоторые функции моего dtwclust
пакета для параллельных вычислений:
library(dtwclust)
library(doParallel)
custom_dist <- new("tsclustFamily", dist = "ngower", control = list(symmetric = TRUE))@dist
workers <- makeCluster(detectCores())
registerDoParallel(workers)
distmat <- custom_dist(df_list)
stopCluster(workers); registerDoSEQ()
Это может будет быстрее для вашего реального случая использования (не так много для небольших выборочных данных здесь).То же самое касается диагонали (поэтому используйте custom_dist(df_list, df_list)
или custom_dist(df_list, pairwise = TRUE)
).См. Раздел 3.2 здесь и документацию tsclustFamily
, если вам нужна дополнительная информация.