Циклы в R с большим набором данных, лучше? - PullRequest
0 голосов
/ 20 ноября 2018

Я использую R и имею большие наборы дат, содержащие 12 224 433 строки.Для каждой строки я хочу сделать корреляционный тест Спирмена по одному вектору и извлечь значения P.Сценарии выглядят так:

pvals <- numeric(nrow(SNP))

for(i in 1:nrow(SNP)) {

  fit <- cor.test(vector, as.numeric(SNP[i,c(4:50)]), method='spearman', exact=FALSE)    

  pvals[i] <-  fit$p.value

  names(pvals)[i] <- paste(SNP$V1[i], SNP$V2[i])

}

Дело в том, что это занимает много времени, я уже подсчитал, что потребовалось 2 часа, чтобы запустить только первые 70000 строк.Так что это может занять 200 часов.Есть ли способ ускорить его?

Ответы [ 3 ]

0 голосов
/ 20 ноября 2018

Вот что я могу предложить, основываясь на информации, которой вы поделились.Я добавил свои мысли в виде комментариев в коде -

# convert all rows to numeric matrix instead of as.numeric(SNP[i,c(4:50)]) in every loop
# also subsetting matrix directly gives you a vector which is what is needed for cor.test()
y <- as.matrix(SNP[, c(4:50)])

# initialize pvals with NA and then replace each value in every loop run
pvals <- rep(NA_real_, nrow(SNP))

for(i in 1:nrow(SNP)) {

  fit <- cor.test(vector, y[i, ], method = 'spearman', exact = FALSE)    

  pvals[i] <-  fit$p.value

}

# you can assign all names in one go instead of doing it in the loop
names(pvals) <- paste(SNP$V1, SNP$V2)

Наконец, у вас есть классический вариант использования для параллельной обработки.Используя пакеты параллельной обработки, такие как foreach, вы можете запускать несколько тестов параллельно и затем объединять их в свой вектор результатов pval.

Также предлагаем вам прочитать книгу 'The R Inferno' для получения дополнительной информации о том, как повысить эффективность кода.

0 голосов
/ 20 ноября 2018

Это был бы хороший кандидат для использования параллельной обработки с пакетом, таким как foreach или future.apply.

В приведенном ниже коде используется future.apply из-за простоты использования этого пакета.

Общая стратегия состоит в том, чтобы выполнить действие, которое вы хотите повторить (т.е. получить p-значения на основе подмножества данных), превратить это действие в функцию и использовать future.apply, чтобы повторить эту функцию дляразличные подмножества данных, которые вы хотите использовать.

library(future.apply)

# Establish method used for parallel processing
  plan(multiprocess)

# Convert the relevant subset of the matrix to numeric
  snp_subset <- SNP[,c(4:50)]
  class(snp_subset) <- 'numeric'

# Define a function to get p.values for a given row of the matrix
  get_pvals <- function(row_index) {
    pvals <- cor.test(vector, snp_subset[row_index,], method = 'spearman', exact = FALSE)$p.value
    names(pvals) <- paste(SNP$V1[row_index], SNP$V2[row_index])
    pvals
  }

# Use parallel processing to get p-values for each row of the matrix
  pvals <- future_sapply(X = seq_len(nrow(SNP)),
                         FUN = get_pvals)
0 голосов
/ 20 ноября 2018

Вы можете использовать apply:

SNP["pvals"] <- apply(SNP[ ,c(4:50)], MARGIN = 1, FUN = function(row) cor.test(vector, as.numeric(row), method='spearman', exact=FALSE)$p.value)

#SNP$pvals
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...