J'utilise R et j'ai un grand ensemble de dates contenant 12 224 433 lignes. Pour chaque ligne, je veux faire un test de corrélation de lancier contre un vecteur et extraire les valeurs P. Les scripts sont comme ceci:

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])

}

Le fait est que cela prend des années, je calcule déjà en quelque sorte, il a fallu 2 heures pour exécuter seulement les 70 000 premières lignes. Cela peut donc prendre 200 heures. Y a-t-il un moyen de l'accélérer?

0
Yun Wang 20 nov. 2018 à 17:23

3 réponses

Meilleure réponse

Ce serait un bon candidat pour utiliser le traitement parallèle avec un package tel que foreach ou future.apply.

Le code ci-dessous utilise future.apply en raison de la simplicité d'utilisation de ce package.

La stratégie générale consiste à effectuer l'action que vous souhaitez répéter (c'est-à-dire à obtenir des valeurs p basées sur un sous-ensemble de données), à transformer cette action en fonction et à utiliser future.apply pour répéter cette fonction pour les différents sous-ensembles de données que vous souhaitez utiliser.

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
bschneidr 20 nov. 2018 à 16:00

Voici ce que je peux suggérer en fonction des informations que vous avez partagées. J'ai ajouté mes pensées sous forme de commentaires dans le code -

# 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)

Enfin, le vôtre est un cas d'utilisation classique du traitement parallèle. En utilisant des packages de traitement parallèle comme foreach, vous pouvez exécuter plusieurs tests en parallèle, puis les combiner dans votre vecteur de résultats pval.

Nous vous suggérons également de lire le livre "The R Inferno" pour plus d'informations sur la façon d'améliorer l'efficacité du code.

3
Shree 20 nov. 2018 à 15:22

Vous pouvez utiliser 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
0
emsinko 20 nov. 2018 à 15:16