Adattare una curva di densità a un istogramma in R


91

Esiste una funzione in R che adatta una curva a un istogramma?

Supponiamo che tu abbia il seguente istogramma

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

Sembra normale, ma è distorta. Voglio adattare una curva normale che è inclinata per avvolgere questo istogramma.

Questa domanda è piuttosto semplice, ma non riesco a trovare la risposta per R su Internet.


Vuoi trovare m e s tali che la distribuzione gaussiana N (m, s) si adatti ai tuoi dati?
SteinNorheim,

Non sono sicuro di cosa significhi ...> _>
user5243421

10
@ mathee: penso che significhi m = media e s = deviazione standard. La distribuzione gaussiana è un altro nome per la distribuzione normale.
Peter Mortensen

Risposte:


154

Se capisco correttamente la tua domanda, probabilmente vorrai una stima della densità insieme all'istogramma:

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

Modifica molto tempo dopo:

Ecco una versione leggermente più elegante:

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) 

insieme al grafico produce:

inserisci qui la descrizione dell'immagine


3
+1 - puoi farlo anche al contrario, ad esempio regolando il grafico della densità per adattarlo all'istogramma?
vonjd

2
Suggerisco di fornire un parametro aggiuntivo a lines(density(X,na.rm= TRUE)poiché il vettore può contenere valori NA.
Anirudh,

30

Tale cosa è facile con ggplot2

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

o per imitare il risultato della soluzione di Dirk

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

28

Ecco come lo faccio:

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

Un esercizio bonus è farlo con il pacchetto ggplot2 ...


Tuttavia, se vuoi qualcosa che sia distorta, puoi eseguire l'esempio di densità dall'alto, trasformare i tuoi dati (ad es. Foo.log & lt; - log (foo) e provare quanto sopra), o provare ad adattare una distribuzione distorta, come il gamma o lognormal (lognormal equivale a prendere il log e adattare un normale, btw).
John Johnson,

2
Ma ciò richiede ancora prima di stimare i parametri della tua distribuzione.
Dirk Eddelbuettel

Questo è un po 'lontano dalla semplice discussione di R, poiché stiamo approfondendo le statistiche teoriche, ma potresti provare questo collegamento per Gamma: en.wikipedia.org/wiki/Gamma_distribution#Parameter_estimation Per lognormal, prendi semplicemente il log (supponendo tutti i dati sono positivi) e lavorare con dati trasformati in log. Per qualsiasi cosa più elaborata, penso che dovresti lavorare con un libro di testo di statistica.
John Johnson,

3
Penso che tu fraintenda come sia il poster originale che tutte le altre risposte siano abbastanza contenti di usare stime non parametriche, come un istogramma vecchia scuola o una stima densamente basata sui dati un po 'più moderna. Le stime parametriche sono ottime se hai buone ragioni per sospettare una distribuzione. Ma qui non è stato così.
Dirk Eddelbuettel,

11

Dirk ha spiegato come tracciare la funzione di densità sull'istogramma. Ma a volte potresti voler andare con l'ipotesi più forte di una distribuzione normale distorta e tracciare quella invece della densità. Puoi stimare i parametri della distribuzione e tracciarla usando il pacchetto sn :

> 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 

Grafico dei dati distribuiti con disallineamento normale

Questo probabilmente funziona meglio su dati più normali:

Un altro grafico normale obliquo


3

Ho avuto lo stesso problema, ma la soluzione di Dirk non sembrava funzionare. Ricevevo questo messaggio di avvertimento ogni volta

"prob" is not a graphical parameter

Ho letto ?histe trovatofreq: a logical vector set TRUE by default.

il codice che ha funzionato per me è

hist(x,freq=FALSE)
lines(density(x),na.rm=TRUE)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.