Histogramm mit logarithmischer Skala und benutzerdefinierten Unterbrechungen

75

Ich versuche, ein Histogramm in R mit einer logarithmischen Skala für y zu erzeugen. Derzeit mache ich:

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

Dies gibt mir ein Histogramm, aber die Dichte zwischen 0 und 1 ist so groß (ungefähr eine Million Wertunterschiede), dass Sie kaum einen der anderen Balken erkennen können.

Dann habe ich versucht:

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

Es gibt mir irgendwie das, was ich will, aber der untere Teil zeigt mir die Werte 1-6 anstelle von 0, 1, 2, 3, 4, 5, 25. Außerdem werden die Daten als Punkte und nicht als Balken angezeigt. barplotfunktioniert aber dann bekomme ich keine untere Achse.

Weegee
quelle

Antworten:

63

Ein Histogramm ist die Dichteschätzung eines armen Mannes. Beachten Sie, dass Sie bei Ihrem Aufruf zur hist()Verwendung von Standardargumenten Häufigkeiten und keine Wahrscheinlichkeiten erhalten. Fügen Sie ,prob=TRUEdem Aufruf hinzu, wenn Sie Wahrscheinlichkeiten wünschen.

Verwenden Sie für das Problem der Protokollachse nicht 'x', wenn die x-Achse nicht transformiert werden soll:

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

Sie erhalten Balken auf einer logarithmischen Skala - das Erscheinungsbild ist immer noch etwas anders, kann aber wahrscheinlich angepasst werden.

Zuletzt können Sie auch hist(log(x), ...) ein Histogramm des Protokolls Ihrer Daten erstellen.

Dirk Eddelbuettel
quelle
Ausgezeichnet! Wie kann ich die untere Achse ändern? Anstatt 1, 2, 3, 4, 5, 6 zu zeigen, möchte ich 0 <= 1, 1 <= 2 usw. zeigen
Weegee
3
Durch Unterdrücken der Achse in plot () und expliziten Aufruf von axis () mit dem 'wo' und 'was' können Sie dies tun.
Dirk Eddelbuettel
51

Eine andere Möglichkeit wäre, das Paket zu verwenden ggplot2.

ggplot(mydata, aes(x = V3)) + geom_histogram() + scale_x_log10()
Thierry
quelle
Dies ist eine sehr gute Antwort und automatisiert viele Details, die später jederzeit angepasst werden können. Vielen Dank!
Sun Bee
10

Aus Ihrer Frage geht nicht ganz hervor, ob Sie eine protokollierte x-Achse oder eine protokollierte y-Achse möchten. Eine protokollierte y-Achse ist keine gute Idee, wenn Balken verwendet werden, da sie bei Null verankert sind, was bei der Protokollierung zu einer negativen Unendlichkeit wird. Sie können dieses Problem umgehen, indem Sie ein Frequenzpolygon oder ein Dichtediagramm verwenden.

Hadley
quelle
10

Dirks Antwort ist großartig. Wenn Sie ein Erscheinungsbild wie das hist, was produziert, wünschen , können Sie auch Folgendes versuchen:

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)

Die letzte Zeile ist optional und fügt Wertelabels direkt unter jedem Balken hinzu. Dies kann für Diagramme im Protokollmaßstab nützlich sein, kann aber auch weggelassen werden.

Ich gehe auch main, xlabund ylabParameter einen Plot Titel, x-Achsen - Etikett zu schaffen, und die y-Achsen - Label.

Quinn Taylor
quelle
8

Führen Sie die Funktion hist () aus, ohne ein Diagramm zu erstellen, transformieren Sie die Zählungen logarithmisch und zeichnen Sie dann die Abbildung.

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

Es sollte genauso aussehen wie das reguläre Histogramm, aber die y-Achse ist log2 Frequenz.

user2596153
quelle
3
Um -Inf zu verhindern, müssen Sie Folgendes verwenden: hist.data$counts[hist.data$counts>0] <- log(hist.data$counts[hist.data$counts>0], 2)
Kory
3

Ich habe eine Funktion zusammengestellt, die sich im Standardfall identisch zu hist verhält, aber das Protokollargument akzeptiert. Es verwendet mehrere Tricks von anderen Postern, fügt aber einige eigene hinzu. hist(x)und myhist(x)identisch aussehen.

Das ursprüngliche Problem würde gelöst werden mit:

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

Die Funktion:

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

Übung für den Leser: Leider funktioniert nicht alles, was mit hist funktioniert, mit myhist in seiner jetzigen Form. Das sollte allerdings mit etwas mehr Aufwand behoben werden können.

Alice Purcell
quelle
3

Hier ist eine hübsche ggplot2-Lösung:

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

Beachten Sie, dass zum Festlegen der Unterbrechungen in geom_histogram diese transformiert werden mussten, um mit scale_x_log10 zu arbeiten

Melissa Key
quelle