Взвешенная корреляция с использованием cov.wt и data.table по группам - PullRequest
2 голосов
/ 22 апреля 2020

У меня есть data.table как этот:

set.seed(12345)
mydt <- data.table(gr1 = sample(letters[1:2], size = 100, replace = TRUE),
        gr2 = sample(letters[3:4], size = 100, replace = TRUE),
        a = rnorm(100), b = rnorm(100), weight = rnorm(100, 5, 1))

gr1 и gr2 определяют членство в группе каждого случая. Я хотел бы получить матрицу корреляции из функции cov.wt по членству в группе, указанному в gr1 и gr2, используя столбец weight. cov.wt возвращает матрицу корреляции, если cor = TRUE. Я могу разделить mydt на gr1 и gr2, а затем использовать lapply, чтобы выполнить вычисления и извлечь каждую из матриц корреляции:

mydt <- split(x = mydt, by = c("gr1", "gr2"), drop = TRUE)

lapply(X = mydt, FUN = function(i) {
  cov.wt(x = as.matrix(i[ , c("a", "b")]), wt = i[ , weight], cor = TRUE)[["cor"]]
})

Я получаю именно то, что хочу:

$b.c
                    a                   b
a 0.99999999999999978 0.26861150206539375
b 0.26861150206539375 0.99999999999999978

$a.c
                     a                    b
a  0.99999999999999978 -0.13281683546112405
b -0.13281683546112405  1.00000000000000000

$b.d
                     a                    b
a  1.00000000000000000 -0.13064774898011455
b -0.13064774898011455  1.00000000000000000

$a.d
                     a                    b
a  0.99999999999999978 -0.61122086293705469
b -0.61122086293705458  0.99999999999999978

Однако с большими наборами данных этот подход довольно медленный. Я хотел бы использовать способ data.table для достижения этой цели, как и в посте Дана Y по этому вопросу . Я борюсь, ты, из-за дополнительных параметров и извлечения корреляционной матрицы из списка, возвращаемого функцией cov.wt. Я попробовал следующее (плюс много вариантов):

mydt[ , .(cov.wt(as.matrix(a, b), wt = weight, cor = TRUE)["cor"]), by = c("gr1", "gr2")]

В конце я получаю только первое значение диагонали каждой матрицы.

Что я делаю неправильно?

1 Ответ

2 голосов
/ 22 апреля 2020

Здесь as.matrix неверно, потому что 'x' - это один элемент, а не несколько (на основе ?as.matrix). Один из вариантов - преобразовать в матрицу с помощью cbind векторов 'a', 'b', а затем обернуть вывод в список (с .())

library(data.table)
out <- mydt[ , .(.(cov.wt(cbind(a,b), wt = weight, cor = TRUE)["cor"])), 
    by = c("gr1", "gr2")]
out$V1
#[[1]]
#[[1]]$cor
#          a         b
#a 1.0000000 0.2686115
#b 0.2686115 1.0000000


#[[2]]
#[[2]]$cor
#           a          b
#a  1.0000000 -0.1328168
#b -0.1328168  1.0000000


#[[3]]
#[[3]]$cor
#           a          b
#a  1.0000000 -0.1306477
#b -0.1306477  1.0000000


#[[4]]
#[[4]]$cor
#           a          b
#a  1.0000000 -0.6112209
#b -0.6112209  1.0000000

ПРИМЕЧАНИЕ. в значениях из-за семян

...