Anpassen einer Dichtekurve an ein Histogramm in R.

91

Gibt es in R eine Funktion, die eine Kurve an ein Histogramm anpasst?

Angenommen, Sie hatten das folgende Histogramm

hist(c(rep(65, times=5), rep(25, times=5), rep(35, times=10), rep(45, times=4)))

Es sieht normal aus, ist aber schief. Ich möchte eine normale Kurve anpassen, die schief ist, um dieses Histogramm zu umwickeln.

Diese Frage ist ziemlich einfach, aber ich kann die Antwort für R im Internet nicht finden.

user5243421
quelle
Möchten Sie m und s so finden, dass die Gaußsche Verteilung N (m, s) zu Ihren Daten passt?
SteinNorheim
Ich bin nicht sicher, was das bedeutet ...> _>
user5243421
10
@mathee: Ich denke er meint m = Mittelwert und s = Standardabweichung. Die Gaußsche Verteilung ist ein anderer Name für die Normalverteilung.
Peter Mortensen

Antworten:

154

Wenn ich Ihre Frage richtig verstehe, möchten Sie wahrscheinlich eine Dichteschätzung zusammen mit dem Histogramm:

X <- c(rep(65, times=5), rep(25, times=5), rep(35, times=10), rep(45, times=4))
hist(X, prob=TRUE)            # prob=TRUE for probabilities not counts
lines(density(X))             # add a density estimate with defaults
lines(density(X, adjust=2), lty="dotted")   # add another "smoother" density

Lange später bearbeiten:

Hier ist eine etwas elegantere Version:

X <- c(rep(65, times=5), rep(25, times=5), rep(35, times=10), rep(45, times=4))
hist(X, prob=TRUE, col="grey")# prob=TRUE for probabilities not counts
lines(density(X), col="blue", lwd=2) # add a density estimate with defaults
lines(density(X, adjust=2), lty="dotted", col="darkgreen", lwd=2) 

zusammen mit dem Diagramm, das es erzeugt:

Geben Sie hier die Bildbeschreibung ein

Dirk Eddelbuettel
quelle
3
+1 - können Sie es auch umgekehrt machen, dh das Dichtediagramm an das Histogramm anpassen?
vonjd
2
Ich schlage vor, zusätzliche Parameter anzugeben, lines(density(X,na.rm= TRUE)da der Vektor NA-Werte enthalten kann.
Anirudh
30

So etwas ist mit ggplot2 einfach

library(ggplot2)
dataset <- data.frame(X = c(rep(65, times=5), rep(25, times=5), 
                            rep(35, times=10), rep(45, times=4)))
ggplot(dataset, aes(x = X)) + 
  geom_histogram(aes(y = ..density..)) + 
  geom_density()

oder um das Ergebnis von Dirks Lösung nachzuahmen

ggplot(dataset, aes(x = X)) + 
  geom_histogram(aes(y = ..density..), binwidth = 5) + 
  geom_density()
Thierry
quelle
28

So mache ich das:

foo <- rnorm(100, mean=1, sd=2)
hist(foo, prob=TRUE)
curve(dnorm(x, mean=mean(foo), sd=sd(foo)), add=TRUE)

Eine Bonusübung besteht darin, dies mit dem ggplot2-Paket zu tun ...

John Johnson
quelle
Wenn Sie jedoch etwas wünschen, das verzerrt ist, können Sie entweder das Dichtebeispiel von oben ausführen, Ihre Daten transformieren (z. B. foo.log & lt; - log (foo) und versuchen Sie es oben) oder versuchen, eine verzerrte Verteilung anzupassen, z das Gamma oder Lognormal (Lognormal ist gleichbedeutend mit dem Aufnehmen des Protokolls und dem Anpassen eines Normalen, übrigens).
John Johnson
2
Dazu müssen Sie jedoch zuerst die Parameter Ihrer Verteilung schätzen.
Dirk Eddelbuettel
Dies ist ein bisschen weit davon entfernt, R einfach zu diskutieren, da wir uns mehr mit theoretischen Statistiken befassen. Sie können jedoch diesen Link für das Gamma ausprobieren: en.wikipedia.org/wiki/Gamma_distribution#Parameter_estimation Für lognormal nehmen Sie einfach das Protokoll (vorausgesetzt Alle Daten sind positiv) und arbeiten mit logarithmisch transformierten Daten. Für etwas schickeres müsste man wohl mit einem Statistiklehrbuch arbeiten.
John Johnson
3
Ich denke, Sie verstehen falsch, dass sowohl das Originalplakat als auch alle anderen Antworten sehr zufrieden sind, nicht parametrische Schätzungen zu verwenden - wie ein Histogramm der alten Schule oder eine etwas modernere datengesteuerte Dichteschätzung. Parametrische Schätzungen sind großartig, wenn Sie guten Grund haben, eine Verteilung zu vermuten. Das war hier aber nicht der Fall.
Dirk Eddelbuettel
11

Dirk hat erklärt, wie die Dichtefunktion über dem Histogramm dargestellt wird. Aber manchmal möchten Sie vielleicht mit der stärkeren Annahme einer verzerrten Normalverteilung gehen und diese anstelle der Dichte zeichnen. Sie können die Parameter der Verteilung schätzen und mit dem sn-Paket zeichnen :

> sn.mle(y=c(rep(65, times=5), rep(25, times=5), rep(35, times=10), rep(45, times=4)))
$call
sn.mle(y = c(rep(65, times = 5), rep(25, times = 5), rep(35, 
    times = 10), rep(45, times = 4)))

$cp
    mean     s.d. skewness 
41.46228 12.47892  0.99527 

Schrägnormal verteiltes Datenplot

Dies funktioniert wahrscheinlich besser bei Daten, die normaler sind:

Eine weitere schief-normale Handlung

fmark
quelle
3

Ich hatte das gleiche Problem, aber Dirks Lösung schien nicht zu funktionieren. Ich bekam jedes Mal diese Warnmeldung

"prob" is not a graphical parameter

Ich lese durch ?hist und fand überfreq: a logical vector set TRUE by default.

Der Code, der für mich funktioniert hat, ist

hist(x,freq=FALSE)
lines(density(x),na.rm=TRUE)
Matias Andina
quelle