Соответствие информации из корреляционной матрицы в соответствии с их отсечкой по p-значению

Я использовал функцию rcorr библиотеки Hmisc для вычисления корреляций и p-значений. Затем извлекали pvalue в матрицу Pval и коэффициенты корреляции в corr матрицу.

Rvalue<-structure(c(1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 
0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 
1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 
1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1), .Dim = c(10L, 
10L), .Dimnames = list(c("41699", "41700", "41701", "41702", 
"41703", "41704", "41705", "41707", "41708", "41709"), c("41699", 
"41700", "41701", "41702", "41703", "41704", "41705", "41707", 
"41708", "41709")))

> Pvalue<-structure(c(NA, 0, 0, 0, 0.0258814351024321, 0, 0, 0, 0, 0, 0, 
NA, 6.70574706873595e-14, 0, 0, 2.1673942640632e-09, 1.08217552696743e-07, 
0.0105345133269157, 0, 0, 0, 6.70574706873595e-14, NA, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, NA, 2.22044604925031e-15, 0, 0, 0, 0, 
0, 0.0258814351024321, 0, 0, 2.22044604925031e-15, NA, 0, 0, 
0, 0.000322310440723728, 0.00298460759118657, 0, 2.1673942640632e-09, 
0, 0, 0, NA, 0, 0, 0, 0, 0, 1.08217552696743e-07, 0, 0, 0, 0, 
NA, 0, 0, 0, 0, 0.0105345133269157, 0, 0, 0, 0, 0, NA, 0, 0, 
0, 0, 0, 0, 0.000322310440723728, 0, 0, 0, NA, 0, 0, 0, 0, 0, 
0.00298460759118657, 0, 0, 0, 0, NA), .Dim = c(10L, 10L), .Dimnames = list(
c("41699", "41700", "41701", "41702", "41703", "41704", "41705", 
"41707", "41708", "41709"), c("41699", "41700", "41701", 
"41702", "41703", "41704", "41705", "41707", "41708", "41709"
)))

Затем я преобразовал матрицу corr в логическую матрицу (0,1), номер один означает хорошую корреляцию. Затем я хочу вычислить хорошие корреляции со значительными p-значениями. Мне нужен список ребер, включая значение p. Я реализовал следующий код:

n=1
m=list()
for(i in 1:nrow(Rvalue))
  {
  for (j in 1:nrow(Rvalue))
    {
if (i<j & Pvalue[i,j]<0.05 & Rvalue[i,j]==1)
      {
      m[[n]]<-c(rownames(Rvalue)[i], colnames(Rvalue)[j], signif(Pvalue[i,j], digits = 4))
        n=n+1  
             }
      }
      print(i)
  }

тогда вывод:

> m
[[1]]
[1] "41699" "41700" "0"    

[[2]]
[2] "41699" "41701" "0"    

[[3]]
[3] "41699" "41702" "0"    

[[4]]
[4] "41699" "41704" "0" 
...

Результат нормальный, но поскольку матрицы очень большие, на это нужно много времени. Как я могу ускорить этот процесс? Обратите внимание, что мне нужны имена узлов. Есть какие-то связанные функции? Я также нашел два похожих вопроса, но не совсем то, что мне нужно (+ и +) . Заранее спасибо.


person user3789396    schedule 29.12.2014    source источник


Ответы (2)


Вы могли бы попробовать

indx <- which(Rvalue==1 & Pvalue < 0.05 & !is.na(Pvalue), arr.ind=TRUE)
d1 <- data.frame(rN=row.names(Rvalue)[indx[,1]], 
               cN=colnames(Rvalue)[indx[,2]], Pval=signif(Pvalue[indx],
                                                                digits=4))

head(d1,2)
#     rN    cN Pval
#1 41700 41699    0
#2 41701 41699    0

Обновлять

Не уверен, почему вы получаете результат same при изменении cutoff. Возможно, что P values будет слишком маленьким, чтобы быть TRUE в cutoffs, который вы пробовали. Вот пример, показывающий, что он действительно возвращает разные значения. Предположим, я создаю функцию из приведенного выше кода,

 f1 <- function(Rmat, Pmat, cutoff){
   indx <- which(Rmat==1 & Pmat < cutoff & !is.na(Pmat), arr.ind=TRUE)
    d1 <- data.frame(rN=row.names(Rmat)[indx[,1]], 
              cN=colnames(Rmat)[indx[,2]], Pval=signif(Pmat[indx],
                                                            digits=4))
 d1}

 f1(R1, P1, 0.05)
 #  rN cN  Pval
 #1  B  A 0.021
 #2  C  A 0.018
 #3  D  A 0.001
 #4  A  B 0.021
 #5  A  C 0.018
 #6  E  C 0.034
 #7  A  D 0.001
 #8  C  E 0.034

 f1(R1, P1, 0.01)
 #  rN cN  Pval
 #1  D  A 0.001
 #2  A  D 0.001

 f1(R1, P1, 0.001)
 #[1] rN   cN   Pval
 #<0 rows> (or 0-length row.names)

данные

set.seed(24)
R1 <- matrix(sample(c(0,1), 5*5, replace=TRUE), 5,5, 
            dimnames=list(LETTERS[1:5], LETTERS[1:5]))
R1[lower.tri(R1)] <- 0
R1 <- R1+t(R1)
diag(R1) <- 1


set.seed(49)
P1 <- matrix(sample(seq(0,0.07, by=0.001), 5*5, replace=TRUE), 5, 5,
       dimnames=list(LETTERS[1:5], LETTERS[1:5]))

P1[lower.tri(P1)] <- 0
P1 <- P1+t(P1)
diag(P1) <- NA
person akrun    schedule 29.12.2014
comment
Спасибо. Это было здорово. Для матрицы 18000 * 18000 потребовалось всего 10 секунд. Непредвиденный. Ваш взлом побудил меня задать вопрос: как я могу обновить кодировку и избавиться от циклов for? Есть отзывы или опыт? - person Sadegh; 29.12.2014
comment
У меня возникла проблема с вашим кодом. Когда я меняю pvalue, результат отсечки не меняется? - person user3789396; 29.12.2014
comment
@ user3079143 Извините, я не понял ваш вопрос. Разве это не удаление / избавление от for петель? - person akrun; 30.12.2014
comment
@ user3079143 Если вы проверите код, особенно indx, он дает вам row/col, где выполняются условия. Возможно, что условия выполнены для диапазона pvalues. - person akrun; 30.12.2014
comment
Уважаемый akrun, ваш код - прекрасный способ убрать циклы for. Я задал общий вопрос. Не могли бы вы порекомендовать мне, как обновить приведенный выше код до чего-то похожего на то, что написали вы. Стоит узнать больше функций? Стоит ли ссылаться на специальные ссылки? - person user3789396; 30.12.2014
comment
@ user3789396 Извините, я неправильно понял ваш вопрос. Я бы порекомендовал вам больше практиковаться, потому что в любом языке программирования практика является ключом. Попробуйте прочитать / решить вопросы в stackoverflow, Rmailing list, которые upgrade будут вам больше, чем просто чтение некоторых книг. - person akrun; 30.12.2014
comment
Уважаемый akrun, спасибо за помощь с кодами, а также за ваши применяемые рекомендации. Я держу за тебя пальцы скрещенными. - person user3789396; 30.12.2014

Поскольку ваша матрица имеет большое количество столбцов и строк, было бы неплохо избежать одновременного выполнения цикла for. Вместо этого вы можете использовать функцию mapply, которая более удобна.

mapply(FUN = NULL , ...)

вместо FUN используйте следующую функцию:

myf= function(x){ x "les then threshold"}

Вы можете использовать mapply(FUN = myf , "Your Matrix") дважды, чтобы проверить, совпадают ли элементы двух матриц корреляции и pvalue с порогом. Сохраните результаты в двух логических матрицах, P1 и P2. Затем умножьте P1 и P2 (прямое умножение).

myf1 = функция (x) {x ‹0,05} myf2 = функция (x) {x> 0,7}

P1 = mapply(FUN = myf1 , matP)

P2 = mapply(FUN = myf2 , matR)

P = P1 * P2

Элементы в P, помеченные как «True», являются желаемыми узлами. Будет работать нормально!

И вот результат для вашего smaple:

P1 = mapply(FUN = myf1 , Pvalue)
P2 = mapply(FUN = myf2 , Rvalue)
P = P1 * P2

NA 1 1 1 0 1 1 0 1 1 1 NA 0 0 0 0 0 0 1 1 1 0 NA 1 0 1 1 1 1 1 1 0 1 NA 0 1 1 0 1 1 0 0 0 0 NA 1 0 1 0 0 1 0 1 1 1 NA 1 1 1 1 1 0 1 1 0 1 NA 1 1 1 0 0 1 0 1 1 1 NA 0 0 1 1 1 1 0 1 1 0 NA 1 1 1 1 1 0 1 1 0 1 NA

person PNS    schedule 30.12.2014
comment
Я не уверен, как это works. Пожалуйста, покажите, используя наборы данных OP. - person akrun; 30.12.2014
comment
Вы можете рассмотреть следующий кодE: myf1 = function (x) {x ‹0,05} myf2 = function (x) {x› 0,7} mat1_p ‹- matrix (sample (c (0,1), 100 * 100, replace = TRUE ), 100, 100) mat2_r ‹- матрица (образец (c (0,1), 100 * 100, replace = TRUE), 100, 100) P1 = mapply (FUN = myf1, mat1_p) P2 = mapply (FUN = myf2 , mat2_r) P = P1 * P2 - person PNS; 30.12.2014
comment
Но это не то, что вы показали в посте, особенно P1 и P2 - person akrun; 30.12.2014
comment
Для матрицы размером 100000 * 100000 на ПК с Celeron 2.1 GHZ и 1 ГБ RAM потребовалось всего 3 секунды. Предполагается, что он будет работать на кластерах за миллисекунды. - person PNS; 30.12.2014
comment
Да, это было мситаке. - person PNS; 30.12.2014
comment
@PaymanNickchi Я не уверен, что это дает тот же результат, которого добивается OP. Например, используя мой набор данных P1, R1 т.е. myf1 <- function(x) {x < 0.05}; myf2 <- function(x) {x==1}; mapply(myf1, P1)*mapply(myf2, R1) Вы можете сравнить это с результатом, который я получил. - person akrun; 30.12.2014
comment
@PaymanNickchi Хочу добавить, что вам здесь даже mapply не нужно. c(myf1(P1)*myf2(R1)) даст тот же результат, что и ваш код. - person akrun; 30.12.2014
comment
Кажется, что mapply работает быстрее, чем использование c (myf1 (P1) * myf2 (P2)). разница во времени для двух маленьких размерных матриц мала, но определенно большая для больших матриц. Я вставил результаты - person PNS; 30.12.2014
comment
Я не делал никаких тестов. Все функции семейства apply представляют собой своего рода циклы, поэтому это удивительно. Сказав это, результат, который вы получили, не является ожидаемым результатом, который хотел OP. - person akrun; 30.12.2014
comment
Вы правы, что mapply быстрее. Здесь mapply применяет функцию к каждому отдельному элементу матрицы по сравнению с myf1(P1), применяемым к матрице в целом. Так что, возможно, индивидуальное применение быстрее, чем весь матричный подход. - person akrun; 30.12.2014
comment
Да, mapply быстрее, чем цикл for. вы можете увидеть страницу stackoverflow.com/questions/5533246/ - person PNS; 30.12.2014
comment
Но я запускаю оба кода, ваш код, учитывая, какая функция и мой код, рассматривая mapply. Кластер, который я запускал, был немного загружен, но ваш код выполняется примерно за 44 секунды, а мой код примерно за 5 минут. Кажется, рейтинг - это то, что, подать заявку и, наконец, для. - person PNS; 30.12.2014
comment
Правильно сделанный цикл for должен быть похож на mapply. Я имел в виду, что memory распределение, если оно правильно выполнено в for цикле, мало что изменит. - person akrun; 30.12.2014
comment
Функции apply работают немного быстрее, чем циклы for, и позволяют избежать переполнения памяти. Они динамически выделяют память для программы, поэтому программа не останавливается. tapply является особым случаем в семействе и использует функции библиотеки C, значительно быстрее, чем другие функции. - person PNS; 30.12.2014
comment
В любом случае, ваш код был отличным, Спасибо, что поделились. - person PNS; 30.12.2014
comment
Вы должны инициализировать список или что-то в этом роде lst <- vector('list', length(1e4)) и т. Д. - person akrun; 30.12.2014
comment
Распределение памяти намного лучше обрабатывается с помощью функций применения, - person PNS; 30.12.2014