Come calcolare la sovrapposizione tra densità di probabilità empiriche?


14

Sto cercando un metodo per calcolare l'area di sovrapposizione tra due stime della densità del kernel in R, come misura della somiglianza tra due campioni. Per chiarire, nel seguente esempio, avrei bisogno di quantificare l'area della regione di sovrapposizione violacea:

library(ggplot2)
set.seed(1234)
d <- data.frame(variable=c(rep("a", 50), rep("b", 30)), value=c(rnorm(50), runif(30, 0, 3)))
ggplot(d, aes(value, fill=variable)) + geom_density(alpha=.4, color=NA)

inserisci qui la descrizione dell'immagine

Una domanda simile è stata discussa qui , con la differenza che devo farlo per dati empirici arbitrari piuttosto che per distribuzioni normali predefinite. Il overlappacchetto affronta questa domanda, ma apparentemente solo per i dati di data e ora, che non funzionano per me. Anche l'indice Bray-Curtis (come implementato nella funzione vegandel pacchetto vegdist(method="bray")) sembra rilevante, ma di nuovo per dati leggermente diversi.

Sono interessato sia all'approccio teorico sia alle funzioni R che potrei impiegare per implementarlo.


2
"quantificare l'area viola" è un problema nella stima, non nel test delle ipotesi, quindi non si può sperare di "realizzare questo utilizzando un test statistico citabile standard ". Ti contraddici. Per favore, chiarisci cosa vuoi veramente . Se tutto ciò che vuoi è una stima dell'area di sovrapposizione di due KDE, è un semplice calcolo.
Glen_b -Restate Monica

@Glen_b grazie per il commento, mi ha aiutato a chiarire il mio pensiero non statistico. Credo che l'area di sovrapposizione tra KDE sia davvero ciò che sto cercando: ho modificato la domanda per riflettere ciò.
mmk,

2
Sarei molto preoccupato per il rischio di arbitrarietà in questo metodo. A seconda della larghezza di banda del kernel, la sovrapposizione calcolata tra due set di dati qualsiasi potrebbe essere uguale a qualsiasi valore scelto nell'intervallo . Le larghezze di banda predefinite non sono ottimizzate per questo scopo e quindi, in teoria, potrebbero dare risultati sorprendenti, arbitrari o incoerenti. I set di dati con limiti naturali (come dati o proporzioni non negativi, ecc.) Introdurrebbero ulteriormente effetti collaterali indesiderati. Cosa fare invece? Inizia con il motivo di questo calcolo: che cosa significa questa "somiglianza"? (0,1)
whuber

La stessa domanda apparve qualche mese dopo, ma si riferiva ai punti di intersezione, tuttavia c'erano alcune note valide che potevano essere prese in considerazione. Nella domanda pregiudiziale si parla di due distribuzioni empiriche. Aggiungo il link in quanto questo post risponde solo a questo tramite la stima della densità del kernel e per le normali distribuzioni. Il link qui sotto credo si estende alla domanda per coppie di distribuzioni empiriche. stats.stackexchange.com/questions/122857/… - Barnaby 7 ore fa
Barnaby

Risposte:


9

L'area di sovrapposizione di due stime della densità del kernel può essere approssimata a qualsiasi grado di precisione desiderato.

1) Dato che i KDE originali sono stati probabilmente valutati su una griglia, se la griglia è la stessa per entrambi (o può essere facilmente fatta la stessa), l'esercizio potrebbe essere facile come prendere semplicemente in ciascun punto e quindi utilizzando la regola trapezoidale o anche una regola del punto medio.min(K1(x),K2(x))

Se i due si trovano su griglie diverse e non possono essere facilmente ricalcolati sulla stessa griglia, è possibile utilizzare l'interpolazione.

2) Potresti trovare il punto (o punti) dell'intersezione e integrare il più basso dei due KDE in ogni intervallo in cui ognuno è più basso. Nel diagramma in alto dovresti integrare la curva blu a sinistra dell'intersezione e quella rosa a destra con qualsiasi mezzo che ti piace / hai a disposizione. Questo può essere fatto essenzialmente esattamente considerando l'area sotto ciascun componente 1 del kernela sinistra o a destra del punto di interruzione.1hK(xxih)

Tuttavia , i commenti di Whuber sopra dovrebbero essere chiaramente tenuti a mente - questa non è necessariamente una cosa molto significativa da fare.


Come si calcola l'errore associato al metodo 1 e al metodo 2?
olliepower

In circostanze normali, entrambi saranno minuscoli rispetto all'errore nelle stime della densità del kernel, quindi non mi preoccuperei troppo. I limiti di errore possono essere calcolati sui metodi trapezoidali e naturalmente su altre integrazioni numeriche - tali calcoli sono piuttosto standard - ma è inutile preoccuparsi dato che i KDE hanno grandi incertezze. Il metodo 2 sarà preciso all'errore di arrotondamento accumulato dei calcoli.
Glen_b -Restinata Monica,

1
Questi suggerimenti metodologici hanno senso, grazie mille per la risposta. Lavorerò sulla realizzazione di questo in R, ma come novizio sarei interessato a suggerimenti su come codificare questo in modo pulito.
mmk

10

Per completezza, ecco come ho finito per farlo in R:

# simulate two samples
a <- rnorm(100)
b <- rnorm(100, 2)

# define limits of a common grid, adding a buffer so that tails aren't cut off
lower <- min(c(a, b)) - 1 
upper <- max(c(a, b)) + 1

# generate kernel densities
da <- density(a, from=lower, to=upper)
db <- density(b, from=lower, to=upper)
d <- data.frame(x=da$x, a=da$y, b=db$y)

# calculate intersection densities
d$w <- pmin(d$a, d$b)

# integrate areas under curves
library(sfsmisc)
total <- integrate.xy(d$x, d$a) + integrate.xy(d$x, d$b)
intersection <- integrate.xy(d$x, d$w)

# compute overlap coefficient
overlap <- 2 * intersection / total

Come notato, c'è un'incertezza e una soggettività intrinseche implicate nella generazione di KDE e anche nell'integrazione.


2
Esiste ora un pacchetto su CRAN chiamato overlappingche stima l'area della sovrapposizione di 2 (o più) distribuzioni empiriche. Consulta la documentazione qui: rdocumentation.org/packages/overlapping/versions/1.5.0/topics/…
Stefan Avey,

x,dx,dx,d

@mmk puoi farlo per densità 2D?
No Lie

4

Innanzitutto, potrei sbagliarmi, ma penso che la tua soluzione non funzionerebbe nel caso in cui vi siano punti multipli in cui si intersecano le stime della densità del kernel (KDE). In secondo luogo, sebbene il overlappacchetto sia stato creato per l'uso con i dati di data e ora, puoi comunque usarlo per stimare l'area di sovrapposizione di due KDE. Devi semplicemente ridimensionare i tuoi dati in modo che vadano da 0 a 2π.
Per esempio :

# simulate two sample    
 a <- rnorm(100)
 b <- rnorm(100, 2)

# To use overplapTrue(){overlap} the scale must be in radian (i.e. 0 to 2pi)
# To keep the *relative* value of a and b the same, combine a and b in the
# same dataframe before rescaling. You'll need to load the ‘scales‘ library.
# But first add a "Source" column to be able to distinguish between a and b
# after they are combined.
 a = data.frame( value = a, Source = "a" )
 b = data.frame( value = b, Source = "b" )
 d = rbind(a, b)
 library(scales) 
 d$value <- rescale( d$value, to = c(0,2*pi) )

# Now you can created the rescaled a and b vectors
 a <- d[d$Source == "a", 1]
 b <- d[d$Source == "b", 1]

# You can then calculate the area of overlap as you did previously.
# It should give almost exactly the same answers.
# Or you can use either the overlapTrue() and overlapEst() function 
# provided with the overlap packages. 
# Note that with these function the KDE are fitted using von Mises kernel.
 library(overlap)
  # Using overlapTrue():
   # define limits of a common grid, adding a buffer so that tails aren't cut off
     lower <- min(d$value)-1 
     upper <- max(d$value)+1
   # generate kernel densities
     da <- density(a, from=lower, to=upper, adjust = 1)
     db <- density(b, from=lower, to=upper, adjust = 1)
   # Compute overlap coefficient
     overlapTrue(da$y,db$y)


  # Using overlapEst():            
    overlapEst(a, b, kmax = 3, adjust=c(0.8, 1, 4), n.grid = 500)

# You can also plot the two KDEs and the region of overlap using overlapPlot()
# but sadly I haven't found a way of changing the x scale so that the scale 
# range correspond to the initial x value and not the rescaled value.
# You can only change the maximum value of the scale using the xscale argument 
# (i.e. it always range from 0 to n, where n is set with xscale = n).
# So if some of your data take negative value, you're probably better off with
# a different plotting method. You can change the x label with the xlab
# argument.  
  overlapPlot(a, b, xscale = 10, xlab= "x metrics", rug=T)
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.