6 votes

Transforming variable density on log scale with R

Je veux tracer la densité de la variable dont la plage est la suivante :

 Min. :-1214813.0
1st Qu. : 1.0
Médiane : 40.0
Moyenne : 303.2
3rd Qu. : 166.0
Max. : 1623990.0

Le graphique linéaire de la densité donne une colonne haute dans la plage [0,1000], avec deux très longues queues vers l'infini positif et négatif. Par conséquent, j'aimerais transformer la variable en une échelle logarithmique, afin de pouvoir voir ce qui se passe autour de la moyenne. Par exemple, je pense à quelque chose comme :

log_values = c( -log10(-values[values<0]), log10(values[values>0]))

ce qui donne :

Min. 1st Qu. Médiane Moyenne 3rd Qu. Max.
-6.085 0.699 1.708 1.286 2.272 6.211

Le principal problème avec cela est le fait que cela n'inclut pas les valeurs 0. Bien sûr, je peux décaler toutes les valeurs loin de 0 avec values[values>=0]+1, mais cela introduirait une certaine distorsion dans les données.

Quelle serait une manière acceptée et scientifiquement solide de transformer cette variable en échelle logarithmique ?

4voto

Matthew Lundberg Points 21747

Ce que vous avez est essentiellement ce que @James suggère. Cela pose problème pour les valeurs dans (-1,1), surtout celles proches de l'origine :

x <- seq(-2, 2, by=.01)
plot(x, sign(x)*log10(abs(x)), pch='.')

entrer la description de l'image ici

Quelque chose comme ceci peut aider :

y <- c(-log10(-x[x<(-1)])-1, x[x >= -1 & x <= 1], log10(x[x>1])+1)

plot(x, y, pch='.')

entrer la description de l'image ici

Ceci est continu. On peut forcer C^1 en utilisant l'intervalle (-1/log(10), 1/log(10)), trouvé en résolvant d/dx log10(x) = 1 :

z <- c( -log10(-x[x<(-1/log(10))]) - 1/log(10)+log10(1/log(10)),
         x[x >= -1/log(10) & x <= 1/log(10)],
         log10(x[x>1/log(10)]) + 1/log(10)-log10(1/log(10))
       )
plot(x, z, pch='.')

entrer la description de l'image ici

3voto

Joris Meys Points 38980

En dehors de la transformation, vous pouvez manipuler l'histogramme lui-même pour obtenir une idée de vos données. Cela vous donne l'avantage que les graphiques restent lisibles et vous avez une idée immédiate de la distribution au centre. Disons que nous simulons les données suivantes :

Data <- c(rnorm(1000,5,10),sample(-10000:10000,10))
> summary(Data)
     Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
-9669.000    -2.119     5.332    85.430    12.460  9870.000 

Ensuite, vous avez quelques approches différentes. Le plus facile pour voir ce qui se passe au centre de vos données est simplement de tracer le centre de vos données. Dans ce cas, disons que je m'intéresse à ce qui se passe entre le premier et le troisième quartile, je peux tracer :

hist(Data,
     xlim=c(-30,30),
     breaks=c(min(Data),seq(-30,30,by=5),max(Data)),
     main="Centre des données"
     )

entrer la description de l'image ici

Si vous voulez également compter les queues, vous pouvez transformer vos données pour réduire les queues et modifier l'axe pour refléter cela, comme suit :

  1. vous attribuez à toutes les valeurs en dehors de la plage d'intérêt une valeur juste en dehors de cette plage
  2. vous tracez l'histogramme, regroupant toutes les valeurs extrêmes dans un seul bin
  3. vous construisez l'axe des X avec les bonnes étiquettes
  4. vous utilisez axis.break() du package plotrix pour ajouter des pauses sur votre axe X, indiquant l'axe discontinu

Pour cela, vous pouvez utiliser quelque chose comme le code suivant :

 require(plotrix)
 # réorganiser les données
 plotdata <- Data
 id <- plotdata < -30 | plotdata > 30
 plotdata[id] <- sign(plotdata[id])*35
 # tracer l'histogramme
 hist(plotdata,
      xlim=c(-40,40),
      breaks=c(-40,seq(-30,30,by=5),40),
      main="Données non affectées",
      xaxt='n'   # laisser l'axe X de côté
      )
 # Construire l'axe X
 axis(1,
      at=c(-40,seq(-30,30,by=10),40),
      labels=c(min(Data),seq(-30,30,by=10),max(Data))
 )
 # ajouter des pauses sur l'axe
 axis.break(axis=1,breakpos=-35)
 axis.break(axis=1,breakpos=35)

Cela vous donne :

entrer la description de l'image ici

Notez que vous obtenez des fréquences brutes en ajoutant freq=TRUE à la fonction hist().

1voto

Matthew Lundberg Points 21747

Je suis en train d'ajouter ceci comme une autre réponse, car bien que l'idée soit similaire, le mappage est fondamentalement différent.

Lorsque de petites valeurs (<1) sont incluses dans un tracé à l'échelle logarithmique, il est courant de tracé log(1 + .) plutôt que log(.).

Reflection à travers l'origine, et nous obtenons quelque chose d'utile:

x <- seq(-2, 2, by=.01)   
w <- c( -log10(1-x[x<0]), x[x==0], log10(1+x[x>0]))

plot(x, w, pch='.')

Il devrait être clair que la fonction est lisse, car les dérivées directionnelles autour de 0 seront également reflétées. entrez la description de l'image ici

Avec des valeurs beaucoup plus grandes dans x:

x <- seq(-10000, 10000, by=.01)
w <- c( -log10(1-x[x<0]), x[x==0], log10(1+x[x>0]))
plot(x, w, pch='.')

entrez la description de l'image ici

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