¿Buenos métodos para gráficos de densidad de variables no negativas en R?


36
plot(density(rexp(100))

Obviamente, toda la densidad a la izquierda de cero representa sesgo.

Estoy buscando resumir algunos datos para los no estadísticos, y quiero evitar preguntas sobre por qué los datos no negativos tienen densidad a la izquierda de cero. Las parcelas son para verificación de aleatorización; Quiero mostrar las distribuciones de variables por grupos de tratamiento y control. Las distribuciones son a menudo exponenciales. Los histogramas son complicados por varias razones.

Una búsqueda rápida en Google me da trabajo de estadísticos sobre núcleos no negativos, por ejemplo: esto .

Pero, ¿se ha implementado algo en R? De los métodos implementados, ¿alguno de ellos es "el mejor" de alguna manera para las estadísticas descriptivas?

EDITAR: incluso si el fromcomando puede resolver mi problema actual, sería bueno saber si alguien ha implementado núcleos basados ​​en literatura sobre estimación de densidad no negativa


3
No es lo que está preguntando, pero no aplicaría la estimación de densidad del núcleo a algo que debería ser exponencial, especialmente para su presentación a audiencias no estadísticas. Usaría una gráfica cuantil-cuantil y explicaría que la gráfica debería ser recta si la distribución fuera exponencial.
Nick Cox

66
plot(density(rexp(100), from=0))?
Stéphane Laurent

44
Una cosa que a veces he hecho con bastante éxito es obtener un kde en los registros y luego transformar la estimación de densidad (sin olvidar el jacobiano). Otra posibilidad sería utilizar una estimación de densidad de registro-spline configurada para conocer el límite.
Glen_b -Reinstate Monica


1
Discutí el método de transformación mencionado por @Glen_b en stata-journal.com/sjpdf.html?articlenum=gr0003 (consulte las páginas 76-78). Los ceros pueden acomodarse usando log (x + 1) en lugar de log y modificando el jacobiano.
Nick Cox

Respuestas:


21

Una solución, tomada de los enfoques para ponderar los bordes de las estadísticas espaciales, es truncar la densidad a la izquierda en cero, pero aumentar los datos que están más cerca de cero. La idea es que cada valor se "distribuya" en un núcleo de unidad de área total centrada en x ; cualquier parte del núcleo que se derrame en territorio negativo se elimina y el núcleo se renormaliza al área de la unidad.XX

Por ejemplo, con un núcleo gaussiano , el peso de renormalización esKh(y,X)=exp(-12((y-X)/ /h)2)/ /2π

w(X)=1/ /0 0K(y,X)rey=11-ΦX,h(0 0)

donde es la función de distribución acumulativa de una variable Normal de media x y desviación estándar h . Las fórmulas comparables están disponibles para otros núcleos.ΦXh

Esto es más simple, y mucho más rápido en cómputo, que tratar de reducir los anchos de banda cerca de . De todos modos, es difícil prescribir exactamente cómo se deben cambiar los anchos de banda cerca de 0 . Sin embargo, este método también es ad hoc : todavía habrá algún sesgo cerca de 0 . Parece funcionar mejor que la estimación de densidad predeterminada. Aquí hay una comparación usando un conjunto de datos grande:0 00 00 0

Figura

El azul muestra la densidad predeterminada, mientras que el rojo muestra la densidad ajustada para el borde en . La verdadera distribución subyacente se traza como una línea punteada como referencia.0 0


Código R

La densityfunción en Rse quejará de que la suma de los pesos no es la unidad, porque quiere que la integral sobre todos los números reales sea la unidad, mientras que este enfoque hace que la integral sobre los números positivos sea igual a la unidad. Como verificación, la última integral se estima como una suma de Riemann.

set.seed(17)
x <- rexp(1000)
#
# Compute a bandwidth.
#
h <- density(x, kernel="gaussian")$bw # $
#
# Compute edge weights.
#
w <- 1 / pnorm(0, mean=x, sd=h, lower.tail=FALSE)
#
# The truncated weighted density is what we want.
#
d <- density(x, bw=h, kernel="gaussian", weights=w / length(x))
d$y[d$x < 0] <- 0
#
# Check: the integral ought to be close to 1:
#
sum(d$y * diff(d$x)[1])
#
# Plot the two density estimates.
#
par(mfrow=c(1,1))
plot(d, type="n", main="Default and truncated densities", xlim=c(-1, 5))
polygon(density(x, kernel="gaussian", bw=h), col="#6060ff80", border=NA)
polygon(d, col="#ff606080", border=NA)
curve(exp(-x), from=0, to=max(x), lty=2, add=TRUE)

21

Una alternativa es el enfoque de Kooperberg y colegas, basado en la estimación de la densidad utilizando splines para aproximar la densidad logarítmica de los datos. Mostraré un ejemplo utilizando los datos de la respuesta de @ whuber, lo que permitirá una comparación de enfoques.

set.seed(17)
x <- rexp(1000)

Necesitará el paquete logspline instalado para esto; instálelo si no es:

install.packages("logspline")

Cargue el paquete y calcule la densidad usando la logspline()función:

require("logspline")
m <- logspline(x)

A continuación, supongo que el objeto dde la respuesta de @ whuber está presente en el espacio de trabajo.

plot(d, type="n", main="Default, truncated, and logspline densities", 
     xlim=c(-1, 5), ylim = c(0, 1))
polygon(density(x, kernel="gaussian", bw=h), col="#6060ff80", border=NA)
polygon(d, col="#ff606080", border=NA)
plot(m, add = TRUE, col = "red", lwd = 3, xlim = c(-0.001, max(x)))
curve(exp(-x), from=0, to=max(x), lty=2, add=TRUE)
rug(x, side = 3)

La gráfica resultante se muestra a continuación, con la densidad de la línea de registro mostrada por la línea roja.

Densidades predeterminadas, truncadas y de línea de registro

Además, el soporte para la densidad se puede especificar mediante argumentos lboundy ubound. Si deseamos suponer que la densidad es 0 a la izquierda de 0 y hay una discontinuidad en 0, podríamos usar lbound = 0en la llamada a logspline(), por ejemplo

m2 <- logspline(x, lbound = 0)

Obteniendo la siguiente estimación de densidad (que se muestra aquí con el majuste de la línea de registro original ya que la figura anterior ya estaba ocupada).

plot.new()
plot.window(xlim = c(-1, max(x)), ylim = c(0, 1.2))
title(main = "Logspline densities with & without a lower bound",
      ylab = "Density", xlab = "x")
plot(m,  col = "red",  xlim = c(0, max(x)), lwd = 3, add = TRUE)
plot(m2, col = "blue", xlim = c(0, max(x)), lwd = 2, add = TRUE)
curve(exp(-x), from=0, to=max(x), lty=2, add=TRUE)
rug(x, side = 3)
axis(1)
axis(2)
box()

La trama resultante se muestra a continuación

Comparación de estimaciones de densidad de línea de registro con y sin un límite inferior en el soporte

xX=0 0x


1
0 01

@whuber Buena pregunta. Solo me encontré con este enfoque recientemente. Sospecho que una buena pregunta para hacer aquí es, ya que los métodos truncados y de línea de registro son solo estimaciones de la densidad real, ¿las diferencias en el ajuste son significativas, estadísticamente? Sin embargo, no estoy seguro de por qué funciona tan bien en cero. Agradecería saber por qué también.
Restablecer Mónica - G. Simpson

@GavinSimpson, gracias por esta buena respuesta. ¿Puedes reproducir la última trama con la última versión de logspline? Para mí, la densidad de ambos, la limitada y la versión ilimitada ir a cero al x = 0.
cel

4

Para comparar distribuciones por grupos (lo que usted dice es el objetivo en uno de sus comentarios) ¿por qué no algo más simple? Las gráficas de caja paralela funcionan bien si N es grande; los gráficos de franjas paralelas funcionan si N es pequeño (y ambos muestran valores atípicos bien, lo que usted dice que es un problema en sus datos).


1
Sí, gracias, eso funciona. Pero me gustan las gráficas de densidad. Muestran más sobre los datos que los diagramas de caja. Supongo que estoy un poco sorprendido de que nada parece haber sido implementado. Tal vez yo mismo implemente una de estas cosas algún día. La gente probablemente lo encontraría útil.
generic_user

1
También me gustan las gráficas de densidad; pero tienes que considerar tu audiencia.
Peter Flom - Restablece a Monica

1
Tengo que estar de acuerdo con @PeterFlom en este caso. No se complique demasiado si su audiencia no tiene conocimientos estadísticos. También podría hacer diagramas de caja comparativos / paralelos con una superposición de diagramas de mariposa en la parte superior. De esa manera, el resumen de la gráfica de caja es visible, así como todos los datos.
doug.numbers

La sugerencia de que diferentes personas comprendan las parcelas agregadas de manera diferente es ciertamente correcta. A pesar de comprender qué es una gráfica de densidad (y comprender que no es una probabilidad), no entiendo qué podría ser una "gráfica de caja paralela". Sugiere un diagrama de coordenadas paralelas, pero sospecho que no es correcto.
DWin

2

Como comenta Stéphane, puede usar from = 0y, además, puede representar sus valores bajo la curva de densidad conrug (x)


44
Corrígeme si estoy equivocado, pero from=0parece que solo suprime el trazado de valores inferiores a 0; no corrige el cálculo por el hecho de que parte de la distribución se ha manchado por debajo de 0.
Nick Cox

1
Eso es correcto. El uso del fromcomando produce un gráfico que parece tener el pico justo a la derecha de cero. Pero si observa los histogramas con bins continuamente más pequeños, muchos datos mostrarán el pico AT cero. El fromes solo un truco gráfico.
generic_user

@ NickCox No estoy seguro, pero no creo que from=0suprima nada. Simplemente comienza la "cuadrícula" en cero.
Stéphane Laurent

La diferencia es si la densidad estimada es distinta de cero para los valores negativos, no si se traza o no. Los investigadores pueden decidir no preocuparse por esto si todo lo que quieren es una visualización.
Nick Cox

@NickCox El comando density(rexp(100), from=0)no tiene nada que ver con el gráfico
Stéphane Laurent
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.