2 votes

Fonction de vectorisation pour calculer l'entropie

J'écris une fonction pour calculer l'indice de diversité de Shannon. J'ai des données larges avec le pourcentage d'observations pour chaque valeur comme variables séparées, chaque ligne représentant un site différent. J'aurai entre 2 et 7 variables selon l'ensemble de données. Pour chaque ligne, je veux calculer l'indice d'information.

equation .

J'ai une fonction de boucle, mais elle est assez lente et je cherche de l'aide pour la vectoriser. Je suis également heureux pour une solution de style tidyverse.

J'ai envisagé d'utiliser le entropy mais il semble s'attendre à ce que les données soient sous forme longue, et bien que je puisse étendre mes données, cela semble inutilement lent. J'ai actuellement 20 000 sites avec des centaines ou des milliers d'observations par site qui ont déjà été résumées dans les distributions en pourcentage au format large. Cette question fonctionne de la même manière avec les données longues.

Exemple de données

# Wide data, between 2 and 7 columns recording the percent of observations with each value, example using 3
df <- data.frame(
  site = 1:3, 
  l1 = c(.33, .5, 0), 
  l2 = c(.33, .5, 0), 
  l3 = c(.33, 0, 1)
)

Fonction de la boucle actuelle

entropy <- function(df, vars) {

  entropy_calc <- function(df, i, vars) {
    sum <- 0
    for (j in vars) { 
      x <- df[i,j]
      if(x != 0) { # skip zeros
        sum <- sum + x * log(x)
      }
    }
    return(-sum)
  }

  entropy <- rep(NA, nrow(df))
  for(i in 1:nrow(df)) {
    entropy[i] <- entropy_calc(df, i, vars)
  }

  return(as.numeric(entropy))
}

df$entropy <- entropy(df, 2:4)

2voto

qdread Points 1049

Cela peut être facilement vectorisé car les fonctions sous-jacentes nécessaires sont déjà vectorisées. Vous n'avez pas besoin de sauter manuellement les zéros car la fonction log(0) renvoie à -Inf y 0*log(0) renvoie à NaN . Vous pouvez omettre le NaN en additionnant les valeurs des cellules en spécifiant na.rm = TRUE .

entropy <- function(p) rowSums(-(p * log(p)), na.rm = TRUE)

entropy(df[,2:4])

Consultez également le diversity() dans le vegan qui fait essentiellement cela, parmi d'autres possibilités.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X