Как сделать так, чтобы R мог вычислять формулу на основе адреса ячейки в матрице? - PullRequest
0 голосов
/ 19 июня 2019

У меня есть общая формула, которая должна применяться к каждой ячейке матрицы.

Sij = Nij / sqrt(Ni*Nj) 

Ni и Nj уже определены в векторе "count" как (A, B, C, D, E).Вы можете думать о них как о Na, Nb, Nc, Nd, Ne;эти значения войдут в знаменатель.

Nij определены в матрице "mat_ans_2".Вы можете думать о них как о Nab, Nac, Nad и т. Д .;эти значения войдут в числитель.

Исходя из этого, я хочу сгенерировать новую матрицу, которая имеет все вычисления Sij.Это будет выглядеть следующим образом:

     A      B     C     D     E
 A   1    0.4842

 B  0.4842  1 

 C                1

 D                      1

 E                            1

Диагональ будет установлена ​​в 1 по умолчанию.Значение, которое входит в AB, получается из этой формулы:

Sab = Nab/sqrt(Na*Nb) = 0.4842

К сожалению, мне не так повезло с генерацией функции "for".

Cij = mat_ans_2
diag(Cij) <- 1
Si = count
Sj = count
Si <- matrix(Si, nrow = length(Si), ncol = length(Si), byrow = TRUE)
Sj <- matrix(Sj, nrow = length(Sj), ncol = length(Sj), byrow = FALSE)
for (i,j in count) { 
   SC <- (Cij)/sqrt(Si * Sj)
       SC[is.na(SC)] <- 0
       diag(SC) <- 1
       return(SC)
   }

Что такоелучший способ, чтобы R смог распознать каждый адрес и выполнить формулу соответственно?

dput(mat_ans_2)
structure(c(1, 1.21666666666667, 0.55, 0.15, 0, 1.21666666666667, 
1, 1.81666666666667, 0.75, 0.35, 0.55, 1.81666666666667, 1, 1.98333333333333, 
0.533333333333333, 0.15, 0.75, 1.98333333333333, 1, 2.7, 0, 0.35, 
0.533333333333333, 2.7, 1), .Dim = c(5L, 5L), .Dimnames = list(
    c("A", "B", "C", "D", "E"), c("A", "B", "C", "D", "E")))

dput(count)
structure(list(class = c("A", "B", "C", "D", "E"), `sum(weight, na.rm = TRUE)` = c(1.59166666666667, 
3.96666666666667, 3.29166666666667, 3.35833333333333, 3.29166666666667
)), row.names = c(NA, -5L), class = c("tbl_df", "tbl", "data.frame"
), .internal.selfref = <pointer: 0x000001e7d1611ef0>)

1 Ответ

3 голосов
/ 19 июня 2019

Итог впереди

mat_ans_2 / sqrt(outer(count[[2]], count[[2]], `*`))

Объяснение / Прохождение

Глядя только на ваш знаменатель, который выглядит для меня как внешний продукт, длячто есть хорошая поддержка:

outer(count[[2]], count[[2]])
#          [,1]      [,2]      [,3]      [,4]      [,5]
# [1,] 2.533403  6.313611  5.239236  5.345347  5.239236
# [2,] 6.313611 15.734444 13.056944 13.321389 13.056944
# [3,] 5.239236 13.056944 10.835069 11.054514 10.835069
# [4,] 5.345347 13.321389 11.054514 11.278403 11.054514
# [5,] 5.239236 13.056944 10.835069 11.054514 10.835069

Это берет каждый из count[[2]] и выполняет его декартово расширение, выполняя определенную функцию.По умолчанию это продукт, но вы также можете указать его вручную / явно с помощью:

outer(count[[2]], count[[2]], `*`)

Внутренне это просто создает два вектора, каждый из которых имеет длину length(count[[2]])^2:

outer(count[[2]], count[[2]], function(a, b) { browser(); a*b; })
# Called from: FUN(X, Y, ...)
# Browse[1]> 
debug at #1: a * b
# Browse[2]> 
a
#  [1] 1.591667 3.966667 3.291667 3.358333 3.291667 1.591667 3.966667 3.291667
#  [9] 3.358333 3.291667 1.591667 3.966667 3.291667 3.358333 3.291667 1.591667
# [17] 3.966667 3.291667 3.358333 3.291667 1.591667 3.966667 3.291667 3.358333
# [25] 3.291667
# Browse[2]> 
cbind(a,b)
#              a        b
#  [1,] 1.591667 1.591667
#  [2,] 3.966667 1.591667
#  [3,] 3.291667 1.591667
#  [4,] 3.358333 1.591667
#  [5,] 3.291667 1.591667
#  [6,] 1.591667 3.966667
#  [7,] 3.966667 3.966667
#  [8,] 3.291667 3.966667
#  [9,] 3.358333 3.966667
# [10,] 3.291667 3.966667
# [11,] 1.591667 3.291667
# [12,] 3.966667 3.291667
# [13,] 3.291667 3.291667
# [14,] 3.358333 3.291667
# [15,] 3.291667 3.291667
# [16,] 1.591667 3.358333
# [17,] 3.966667 3.358333
# [18,] 3.291667 3.358333
# [19,] 3.358333 3.358333
# [20,] 3.291667 3.358333
# [21,] 1.591667 3.291667
# [22,] 3.966667 3.291667
# [23,] 3.291667 3.291667
# [24,] 3.358333 3.291667
# [25,] 3.291667 3.291667

Отсюда достаточно легко завершить знаменатель с помощью

sqrt(outer(count[[2]], count[[2]], `*`))

Поскольку числитель уже является матрицей с такими же размерами, это просто простое деление:

out <- mat_ans_2 / sqrt(outer(count[[2]], count[[2]], `*`))
out
#            A          B         C          D          E
# A 0.62827225 0.48420882 0.2402861 0.06487887 0.00000000
# B 0.48420882 0.25210084 0.5027528 0.20548802 0.09686062
# C 0.24028613 0.50275277 0.3037975 0.59652120 0.16202532
# D 0.06487887 0.20548802 0.5965212 0.29776675 0.81207088
# E 0.00000000 0.09686062 0.1620253 0.81207088 0.30379747

Поскольку вы сказаливам нужна была диагональ все 1 с, тогда

diag(out) <- 1
out
#            A          B         C          D          E
# A 1.00000000 0.48420882 0.2402861 0.06487887 0.00000000
# B 0.48420882 1.00000000 0.5027528 0.20548802 0.09686062
# C 0.24028613 0.50275277 1.0000000 0.59652120 0.16202532
# D 0.06487887 0.20548802 0.5965212 1.00000000 0.81207088
# E 0.00000000 0.09686062 0.1620253 0.81207088 1.00000000
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...