web-dev-qa-db-fra.com

Histogramme avec échelle logarithmique et ruptures personnalisées

J'essaie de générer un histogramme en R avec une échelle logarithmique pour y. Actuellement, je fais:

hist(mydata$V3, breaks=c(0,1,2,3,4,5,25))

Cela me donne un histogramme, mais la densité entre 0 et 1 est si grande (différence d'environ un million de valeurs) que vous pouvez à peine distinguer les autres barres.

Ensuite, j'ai essayé de faire:

mydata_hist <- hist(mydata$V3, breaks=c(0,1,2,3,4,5,25), plot=FALSE)
plot(rpd_hist$counts, log="xy", pch=20, col="blue")

Cela me donne en quelque sorte ce que je veux, mais le bas me montre les valeurs 1-6 plutôt que 0, 1, 2, 3, 4, 5, 25. Il montre également les données sous forme de points plutôt que de barres. barplot fonctionne mais je n'obtiens aucun axe inférieur.

72
Weegee

Un histogramme est une estimation de densité d'un pauvre. Notez que dans votre appel à hist() en utilisant des arguments par défaut, vous obtenez fréquences pas des probabilités - ajoutez ,prob=TRUE À l'appel si vous voulez des probabilités.

Quant au problème de l'axe du journal, n'utilisez pas 'x' si vous ne voulez pas que l'axe des x soit transformé:

plot(mydata_hist$count, log="y", type='h', lwd=10, lend=2)

vous donne des barres sur une échelle log-y - l'apparence est toujours un peu différente mais peut probablement être modifiée.

Enfin, vous pouvez également faire hist(log(x), ...) pour obtenir un histogramme du journal de vos données.

60
Dirk Eddelbuettel

Une autre option serait d'utiliser le package ggplot2.

ggplot(mydata, aes(x = V3)) + geom_histogram() + scale_x_log10()
46
Thierry

Il n'est pas tout à fait clair de votre question si vous voulez un axe x enregistré ou un axe y enregistré. Un axe Y enregistré n'est pas une bonne idée lorsque vous utilisez des barres car elles sont ancrées à zéro, ce qui devient une infinité négative lors de la journalisation. Vous pouvez contourner ce problème en utilisant un polygone de fréquence ou un tracé de densité.

10
hadley

La réponse de Dirk est excellente. Si vous voulez une apparence semblable à ce que hist produit, vous pouvez également essayer ceci:

buckets <- c(0,1,2,3,4,5,25)
mydata_hist <- hist(mydata$V3, breaks=buckets, plot=FALSE)
bp <- barplot(mydata_hist$count, log="y", col="white", names.arg=buckets)
text(bp, mydata_hist$counts, labels=mydata_hist$counts, pos=1)

La dernière ligne est facultative, elle ajoute des étiquettes de valeur juste sous le haut de chaque barre. Cela peut être utile pour les graphiques à échelle logarithmique, mais peut également être omis.

Je passe également les paramètres main, xlab et ylab pour fournir un titre de tracé, une étiquette d'axe x et une étiquette d'axe y.

10
Quinn Taylor

Exécutez la fonction hist () sans créer de graphique, transformez les nombres en journaux, puis tracez la figure.

hist.data = hist(my.data, plot=F)
hist.data$counts = log(hist.data$counts, 2)
plot(hist.data)

Il devrait ressembler à l'histogramme normal, mais l'axe y sera la fréquence log2.

7
user2596153

Voici une jolie solution ggplot2:

library(ggplot2)
library(scales)  # makes pretty labels on the x-axis

breaks=c(0,1,2,3,4,5,25)

ggplot(mydata,aes(x = V3)) + 
  geom_histogram(breaks = log10(breaks)) + 
  scale_x_log10(
    breaks = breaks,
    labels = scales::trans_format("log10", scales::math_format(10^.x))
  )

Notez que pour définir les ruptures dans geom_histogram, elles devaient être transformées pour fonctionner avec scale_x_log10

3
Melissa Key

J'ai mis en place une fonction qui se comporte de manière identique à hist dans le cas par défaut, mais accepte l'argument log. Il utilise plusieurs astuces d'autres affiches, mais en ajoute quelques-unes. hist(x) et myhist(x) sont identiques.

Le problème d'origine serait résolu avec:

myhist(mydata$V3, breaks=c(0,1,2,3,4,5,25), log="xy")

La fonction:

myhist <- function(x, ..., breaks="Sturges",
                   main = paste("Histogram of", xname),
                   xlab = xname,
                   ylab = "Frequency") {
  xname = paste(deparse(substitute(x), 500), collapse="\n")
  h = hist(x, breaks=breaks, plot=FALSE)
  plot(h$breaks, c(NA,h$counts), type='S', main=main,
       xlab=xlab, ylab=ylab, axes=FALSE, ...)
  axis(1)
  axis(2)
  lines(h$breaks, c(h$counts,NA), type='s')
  lines(h$breaks, c(NA,h$counts), type='h')
  lines(h$breaks, c(h$counts,NA), type='h')
  lines(h$breaks, rep(0,length(h$breaks)), type='S')
  invisible(h)
}

Exercice pour le lecteur: Malheureusement, tout ce qui fonctionne avec hist ne fonctionne pas avec myhist tel quel. Cela devrait être réparable avec un peu plus d'efforts, cependant.

3
Alice Purcell