Матричная версия cor.test()

Cor.test() принимает векторы x и y в качестве аргументов, но у меня есть целая матрица данных, которые я хочу проверить попарно. Cor() прекрасно принимает эту матрицу в качестве аргумента, и я надеюсь найти способ сделать то же самое для cor.test().

Общий совет от других людей, кажется, использовать cor.prob():

https://stat.ethz.ch/pipermail/r-help/2001-November/016201.html

Но эти p-значения не такие, как те, что генерируются cor.test()!!! Cor.test() также кажется лучше приспособленным для попарного удаления (у меня довольно много недостающих данных в моем наборе данных), чем cor.prob().

У кого-нибудь есть альтернативы cor.prob()? Если решение включает вложенные циклы for, пусть будет так (я достаточно новичок в R, так что даже это для меня проблематично).


person Atticus29    schedule 28.10.2012    source источник
comment
Вы можете использовать lapply с cor.test или векторизовать функцию и передать ее outer, как показано в этой ссылке: stackoverflow.com/questions/9917242/   -  person Tyler Rinker    schedule 28.10.2012


Ответы (5)


corr.test в пакете psych предназначен для этого:

library("psych")
data(sat.act)
corr.test(sat.act)

Как отмечалось в комментариях, чтобы воспроизвести p-значения из базовой cor.test() функции по всей матрице, необходимо отключить корректировку p-значений для нескольких сравнения (по умолчанию используется метод корректировки Холма):

 corr.test(sat.act, adjust = "none")

[Но будьте осторожны при интерпретации этих результатов!]

person Sacha Epskamp    schedule 28.10.2012
comment
красиво, зачем изобретать велосипед. +1 г - person Tyler Rinker; 29.10.2012
comment
Просто примечание, если вы хотите, чтобы результаты соответствовали статистике cor.test используйте corr.test(mtcars, adjust="none") - person Tyler Rinker; 29.10.2012
comment
Тайлер, я это заметил. Спасибо! Вы оба были потрясающими и очень полезными! - person Atticus29; 29.10.2012
comment
Если у вас большая матрица, это будет очень-очень медленно! Чтобы ускорить его, установите аргумент ci=F, который занимает примерно в два раза больше времени, чем cor(), тогда как с ci=T (по умолчанию) это может занять в 100 раз больше времени. - person sssheridan; 29.04.2016
comment
Я получил ошибку (ошибка в corr.test(x, y, Adjust = none, ci = F): объект 'sef' не найден), когда я попытался сделать ci = F. Я написал ответ ниже, который берет важный код из функции и просто запускает cor() и выдает pvalues. - person Nick Clark; 14.09.2017

Если вам строго нужны pvalues ​​в матричном формате из cor.test, вот решение, бессовестно украденное у Винсента (ССЫЛКА):

cor.test.p <- function(x){
    FUN <- function(x, y) cor.test(x, y)[["p.value"]]
    z <- outer(
      colnames(x), 
      colnames(x), 
      Vectorize(function(i,j) FUN(x[,i], x[,j]))
    )
    dimnames(z) <- list(colnames(x), colnames(x))
    z
}

cor.test.p(mtcars)

Примечание. Tommy также предлагает более быстрое решение, хотя и менее простое в реализации. О, и нет циклов :)

Изменить В моем пакете qdapTools есть функция v_outer, которая значительно упрощает эту задачу:

library(qdapTools)
(out <- v_outer(mtcars, function(x, y) cor.test(x, y)[["p.value"]]))
print(out, digits=4)  # for more digits
person Tyler Rinker    schedule 28.10.2012
comment
Отредактировано и [[3]] индексирует список, который выводит cor.test. Третий элемент этого списка — p.value. - person Tyler Rinker; 29.10.2012
comment
@TylerRinker Я считаю, что код более понятен, если использовать именованную версию вывода списка. Немного яснее, если вместо cor.test(x, y)[[3]] у вас есть cor.test(x, y)[["p.value"]], что вы извлекаете p-значение из теста. - person Dason; 29.10.2012
comment
@Dason Дасон, я согласен, я просто был ленив, потому что догадался, какой индекс был основан на выводе, и был слишком ленив, чтобы использовать str или names в выводе из cor.test, чтобы узнать. Я действительно виню в этом ботов. Они автоматизировали нашу жизнь до такой степени, что мы стали слишком ленивыми. - person Tyler Rinker; 29.10.2012
comment
Вы хотите сказать, что ваше предложение может привести к тому же результату, что и p.mat.all <- psych:::cor.test(M.cor, alternative = "two.sided", method = c("pearson", "kendall", "spearman"), adjust = "none", ci = F)? - - Я думаю, вы просто используете Pearson cor здесь. - person Léo Léopold Hertz 준영; 10.11.2016
comment
Мне нравится этот метод, так что спасибо! Мне нужно было вычислить p-значения для нескольких парных корреляций, а rcorr не работал с моими данными, потому что он состоял из очень больших векторов. Это помогло! Спасибо!! - person Rodrigo Duarte; 10.01.2020

Вероятно, самый простой способ — использовать rcorr() от Hmisc. Для этого потребуется только матрица, поэтому используйте rcorr(as.matrix(x)), если ваши данные находятся в data.frame. Он вернет вам список с: 1) матрицей r попарно, 2) матрицей попарно n, 3) матрицей значений p для r. Он автоматически игнорирует недостающие данные.

В идеале функция такого типа должна также принимать data.frames и выводить доверительные интервалы в соответствии с 'Новая статистика'.

person CoderGuy123    schedule 26.05.2015
comment
Это идеальный вариант, но он не работает с моим большим набором данных (50 переменных (которые я оцениваю по сходству) x 46 000 000 наблюдений). Выдает ошибку памяти. - person Rodrigo Duarte; 10.01.2020
comment
Попробуйте wtd.cors() из пакета weights. Я думаю, что он использует какое-то быстрое приближение. Если вам нужны значения p и т. д., вы можете использовать wtd.cor() для каждой парной переменной. Если вам все еще нужна большая скорость, вы можете рассмотреть возможность выполнения одной переменной за раз и сохранения z-оценок между вычислениями, так как это сэкономит операцию их пересчета несколько раз. - person CoderGuy123; 10.01.2020

Принятое решение (функция corr.test в пакете psych) работает, но очень медленно для больших матриц. Я работал с матрицей экспрессии генов (~ 20 000 на ~ 1000), коррелированной с матрицей чувствительности к лекарствам (~ 1000 на ~ 500), и мне пришлось остановить ее, потому что это длилось вечно.

Я взял некоторый код из пакета psych и вместо этого напрямую использовал функцию cor() и получил гораздо лучшие результаты:

# find (pairwise complete) correlation matrix between two matrices x and y
# compare to corr.test(x, y, adjust = "none")
n <- t(!is.na(x)) %*% (!is.na(y)) # same as count.pairwise(x,y) from psych package
r <- cor(x, y, use = "pairwise.complete.obs") # MUCH MUCH faster than corr.test()
cor2pvalue = function(r, n) {
  t <- (r*sqrt(n-2))/sqrt(1-r^2)
  p <- 2*(1 - pt(abs(t),(n-2)))
  se <- sqrt((1-r*r)/(n-2))
  out <- list(r, n, t, p, se)
  names(out) <- c("r", "n", "t", "p", "se")
  return(out)
}
# get a list with matrices of correlation, pvalues, standard error, etc.
result = cor2pvalue(r,n)

Даже с двумя матрицами 100 х 200 разница была ошеломляющей. Секунда-две против 45 секунд.

> system.time(test_func(x,y))
   user  system elapsed 
  0.308   2.452   0.130 
> system.time(corr.test(x,y, adjust = "none"))
   user  system elapsed 
 45.004   3.276  45.814 
person Nick Clark    schedule 14.09.2017
comment
Примечание. Я только что видел выше, что вы можете использовать corr.test() с опцией ci = F, чтобы сделать это быстрее. Тем не менее, это дало мне ошибку, когда я попробовал это. - person Nick Clark; 14.09.2017
comment
Похоже, в коде есть небольшая ошибка. Смотрите мое исправление здесь (я знаю, что оно доступно только для чтения): github.com/cran /psych/pull/2/commits/ Я написал об этом по электронной почте сопровождающему пакета. - person Nick Clark; 14.09.2017

«Принятое решение (функция corr.test в пакете psych) работает, но очень медленно для больших матриц».

Если использовать ci=FALSE, то скорость намного быстрее. По умолчанию найдены доверительные интервалы. Однако это приводит к небольшому замедлению скорости. Итак, только для rs, ts и ps установите ci=FALSE.

person user10412376    schedule 25.09.2018