Comment transformer des valeurs négatives en logarithmes?

12

Je voudrais savoir comment transformer des valeurs négatives en Log(), car j'ai des données hétéroscédastiques. J'ai lu que cela fonctionne avec la formule Log(x+1)mais cela ne fonctionne pas avec ma base de données et je continue à obtenir des NaN en conséquence. Par exemple, je reçois ce message d'avertissement (je n'ai pas mis ma base de données complète parce que je pense qu'avec une de mes valeurs négatives suffit pour montrer un exemple):

> log(-1.27+1)
[1] NaN
Warning message:
In log(-1.27 + 1) : NaNs produced
> 

Merci d'avance

MISE À JOUR:

Voici un histogramme de mes données. Je travaille avec des séries paléontologiques de mesures chimiques, par exemple la différence entre des variables comme Ca et Zn est trop grande, alors j'ai besoin d'un certain type de standardisation des données, c'est pourquoi je teste la log()fonction. entrez la description de l'image ici

Ce sont mes données brutes

Darwin PC
la source
2
Le logarithme n'est défini que pour les nombres positifs et est généralement utilisé comme une transformation statistique sur des données positives afin qu'un modèle préserve cette positivité. La log(x+1)volonté de transformation n'est définie que pour x > -1, alors elle x + 1est positive. Il serait bon de connaître la raison pour laquelle vous souhaitez vous connecter pour transformer vos données.
Matthew Drury
3
Dites-nous en plus sur les données, y compris la plage, la moyenne, les fréquences des valeurs négatives, nulles et positives. Il se pourrait qu'un modèle linéaire généralisé avec un lien logarithmique soit plus logique pour les données tant qu'il est raisonnable de penser que la réponse moyenne est positive. Il se pourrait que vous ne vous transformiez pas du tout.
Nick Cox
6
Merci d'avoir ajouté des détails. Pour de telles données, 0 a une signification (égalité!) Qui doit être respectée, voire préservée . Pour cela et pour d'autres raisons, j'utiliserais des racines cubiques. En pratique, vous aurez besoin de quelques variations sign(x) * (abs(x))^(1/3), les détails dépendant de la syntaxe du logiciel. Pour en savoir plus sur les racines cubiques, voir par exemple stata-journal.com/sjpdf.html?articlenum=st0223 (voir en particulier pp.152-3). Nous avons utilisé des racines cubiques pour aider à visualiser une variable de réponse qui peut être de nature
Nick Cox
8
Pourquoi ne transformez-vous pas les variables d' origine au lieu des différences?
whuber
4
Vous avez résolu le problème mathématique. La suggestion de whuber ou les racines cubiques seraient toujours, je pense, plus faciles à utiliser, surtout si la constante est purement empirique ou varie entre les variables. Une bonne règle pour le choix des transformations consiste uniquement à utiliser des transformations qui fonctionneraient pour des données similaires que vous pouvez imaginer. Ainsi, "fonctionne" pour mais échouerait si votre prochain lot était limité par ..x > - 4 - 5log(x+4)x>45
Nick Cox

Réponses:

14

Étant donné que le logarithme n'est défini que pour les nombres positifs, vous ne pouvez pas prendre le logarithme des valeurs négatives. Cependant, si vous souhaitez obtenir une meilleure distribution de vos données, vous pouvez appliquer la transformation suivante.

Supposons que vous ayez biaisé les données négatives:

x <- rlnorm(n = 1e2, meanlog = 0, sdlog = 1)
x <- x - 5
plot(density(x))

alors vous pouvez appliquer une première transformation pour que vos données se trouvent dans :(1,1)

z <- (x - min(x)) / (max(x) - min(x)) * 2 - 1
z <- z[-min(z)]
z <- z[-max(z)]
min(z); max(z)

et enfin appliquer la tangente hyperbolique inverse:

t <- atanh(z)
plot(density(t))

Maintenant, vos données semblent distribuées approximativement normalement. Ceci est également appelé transformation de Fisher.

stochazesthai
la source
9
Vous avez résolu le problème mathématique immédiat. Mais je ne pense pas que les consommateurs de résultats statistiques les plus probables trouveraient facilement comme une échelle de réponse et dans la modélisation, vous devriez penser à la structure d'erreur qui a du sens. L'échelle serait sensible au minimum et au maximum empiriques. atanh[(xmin(x))/(max(x)min(x))]
Nick Cox
2
@NickCox Vous avez absolument raison. Peut-être que si l'OP ajoute plus de détails sur son problème, nous pourrions trouver une solution alternative!
stochazesthai
L'argument intérieur de mon premier commentaire n'est pas ce qui se transforme, mais l'esprit de mon commentaire est, je pense, inchangé.
Nick Cox
Cher @stochazesthai merci pour votre explication détaillée, mais je ne peux pas appliquer votre code à mes données. J'ai mis à jour ma question avec un lien de mes données brutes à la fin.
Darwin PC
Les déclarations z <- z[-max(z)]et z <- z[-min(z)]réduisent de manière inappropriée zà une seule valeur. La fonction générale atanh(((x - min(x)) / (max(x) - min(x))))produit également Infpour les valeurs minimale et maximale de x.
Max Ghenis
-1

Pour le transformer en échelle logarithmique, recherchez d'abord le log du nombre positif puis multipliez-le par son signe, le code suivant devrait le faire.

transform_to_log_scale <- function(x){
    if(x==0){
        y <- 1
    } else {
        y <- (sign(x)) * (log(abs(x)))
    }
        y 
    }

En utilisant l'exemple ci-dessus, nous pouvons tracer la distribution asymétrique suivante

x <- rlnorm(n = 1e2, meanlog = 0, sdlog = 1)
x <- x - 5
plot(density(x))

entrez la description de l'image ici

Après avoir utilisé la fonction de transformation comme suit, nous obtenons une distribution qui semble plus «normale»

plot(density(sapply(x,FUN=transform_logs_scale)))

entrez la description de l'image ici

yosemite_k
la source
3
(1) La plupart des langages de programmation ( Rinclus) implémentent la fonction signum (qui renvoie -1 pour les nombres négatifs, 1 pour les nombres positifs et 0 pour zéro). Son utilisation serait plus expressive et plus rapide. (2) Votre proposition est médiocre pour analyser des données comme celles illustrées, car elle présente une discontinuité énorme à zéro!
whuber
merci pour signum, je ne le savais pas, je me demande comment il est mis en œuvre
yosemite_k
3
Il existe différentes manières. Dans de nombreuses architectures de processeurs, un bit de signe est défini après de nombreuses opérations, il peut donc être utilisé. Dans la représentation en virgule flottante à double précision IEEE, le signe peut être trouvé en inspectant un seul bit (plus un autre test rapide pour un vrai zéro). Dans les architectures en pipeline avec branchement prédictif, etc., il est généralement beaucoup plus efficace de ne pas créer de branchement si possible, c'est pourquoi l'utilisation de la version intégrée de signum peut être un gain de calcul significatif. Soit dit en passant, définir y <- 1lorsque semble arbitraire - cela pourrait vraiment bousiller une analyse statistique. x=0
whuber