Pregunta

Tengo una trama de datos "foo" con este aspecto

Date       Return
1998-01-01  0.02
1998-01-02  0.04
1998-01-03 -0.02
1998-01-04 -0.01
1998-01-05  0.02
...
1998-02-01  0.1
1998-02-02 -0.2
1998-02-03 -0.1
etc.

Me gustaría añadir a esta trama de datos una nueva columna que me muestra el valor de la densidad de la devolución correspondiente. Probé:

foo$density <- for(i in 1:length(foo$Return)) density(foo$Return, 
from = foo$Return[i], to = foo$Return[i], n = 1)$y

Pero no funcionó. Realmente, no tengo problemas para aplicar una "función" para cada fila. Pero tal vez también hay otra manera de hacerlo, no usar densidad ()?

Lo que esencialmente gustaría hacer es extraer los valores de densidad empotrados de densidad () a los retornos en foo. Si sólo hago trama (densidad (foo $ Retorno)) me da la curva, sin embargo, me gustaría tener los valores de densidad unidos a los rendimientos.

@Joris:

foo$density <- density(foo$Return, n=nrow(foo$Return))$y 

calcula algo, sin embargo, parece volver valores de densidad equivocadas.

Gracias por ayudarme! Dani

¿Fue útil?

Solución

En el segundo pensamiento, olvidarse de la función de densidad, de repente me di cuenta de lo que quería hacer. La mayoría de las funciones de densidad devuelven una rejilla, por lo que no le damos la evaluación en los puntos exactos. Si quieres que, por ejemplo, se puede usar el paquete sm:

require(sm)
foo <- data.frame(Return=rpois(100,5))
foo$density <- sm.density(foo$Return,eval.points=foo$Return)$estimate
# the plot
id <- order(foo$Return)
hist(foo$Return,freq=F)
lines(foo$Return[id],foo$density[id],col="red")

Si el número de valores diferentes no es tan grande, puede utilizar ave ():

foo$counts <- ave(foo$Return,foo$Return,FUN=length)

Si el propósito es parcela una función de densidad, no hay necesidad de calcular como lo hizo. Sólo el uso

plot(density(foo$Return))

O, para añadir un histograma debajo (la mente la opción freq=F)

hist(foo$Return,freq=F)
lines(density(foo$Return),col="red")

Otros consejos

Una alternativa a sm.density es evaluar la densidad en una cuadrícula más fina que por defecto, y el uso approx o approxfun para dar los valores interpolados de la densidad en el Returns desea. Aquí hay un ejemplo con datos ficticios:

set.seed(1)
foo <- data.frame(Date = seq(as.Date("2010-01-01"), as.Date("2010-12-31"),
                             by = "days"),
                  Returns = rnorm(365))
head(foo)
## compute the density, on fin grid (512*8 points)
dens <- with(foo, density(Returns, n = 512 * 8))

En este punto, se podría utilizar approx() para interpolar los componentes x y y de la densidad de regresar, pero yo prefiero approxfun() el que hace lo mismo, pero devuelve una función que puede utilizar para hacer la interpolación. En primer lugar, generar la función de interpolación:

## x and y are components of dens, see str(dens)
BAR <- with(dens, approxfun(x = x, y = y))

Ahora usted puede utilizar para volver BAR() la densidad interpolado en cualquier momento que desee, por ejemplo, por primera Returns:

> with(foo, BAR(Returns[1]))
[1] 0.3268715

Para terminar el ejemplo, agregar la densidad para cada dato en Returns:

> foo <- within(foo, Density <- BAR(Returns))
> head(foo)
        Date    Returns   Density
1 2010-01-01 -0.6264538 0.3268715
2 2010-01-02  0.1836433 0.3707068
3 2010-01-03 -0.8356286 0.2437966
4 2010-01-04  1.5952808 0.1228251
5 2010-01-05  0.3295078 0.3585224
6 2010-01-06 -0.8204684 0.2490127

Para ver lo bien que la interpolación está haciendo, podemos trazar la densidad y la versión interpolada y comparar. Tenga en cuenta que tenemos que solucionar Returns porque para lograr el efecto que queremos, necesidades lines para ver los datos de aumentar Para:

plot(dens)
with(foo, lines(sort(Returns), BAR(sort(Returns)), col = "red"))

¿Qué le da algo como esto: Densidad (en negro) y versión interpolada (en rojo)

Mientras se evalúa la densidad suficientemente fina en un conjunto de puntos (512 * 8 en el ejemplo anterior) que no debería tener ningún problema y será empujado difícil saber la diferencia entre la versión interpolada y lo real . Si usted tiene "huecos" en los valores de su Returns entonces usted podría encontrar que, como se acaba de lines() une los puntos que usted pide para representar gráficamente, que segmentos de línea recta podrían no seguir la densidad de negro en las posiciones de los huecos. Esto es sólo un artefacto de las lagunas y cómo funciona lines(), no es un problema con la interpolación.

Si ignoramos el tema density, lo cual, no parecen haber comprendido cómo configurar un bucle @Joris responde las. Lo que va a devolver a partir del bucle es el valor NULL. Este es el valor que está siendo insertado en foo$density y que no no trabajo porque es el NULL, que significa que es un componente de vacío, es decir, no existe como lo que se refiere R. Ver ?'for' para más detalles.

> bar <- for(i in 1:10) {
+     i + 1
+ }
> bar
NULL

> foo <- data.frame(A = 1:10, B = LETTERS[1:10])
> foo$density <- for(i in seq_len(nrow(foo))) {
+     i + 1
+ }
> head(foo) ## No `density`
  A B
1 1 A
2 2 B
3 3 C
4 4 D
5 5 E
6 6 F

Si desea insertar el valor de retorno para cada iteración del bucle, debe hacer la tarea dentro de el bucle, y eso significa que debe pre-asignar el espacio de almacenamiento antes de entrar en el bucle , p.ej el bucle anterior si queríamos tener i + 1 para i en 1, ..., 10, podríamos hacer esto:

> bar <- numeric(length = 10)
> for(i in seq_along(bar)) {
+     bar[i] <- i + 1
+ }
> bar
 [1]  2  3  4  5  6  7  8  9 10 11

Por supuesto, usted no haría un cálculo de este tipo a través de un bucle, ya que R es vectorizado y trabajará con vectores de números en lugar de tener que código de cada elemento de cálculo por elementos como puede ser que en C o en otros lenguajes de programación .

> bar <- 1:10 + 1
> bar
 [1]  2  3  4  5  6  7  8  9 10 11

Observe que R se ha convertido 1 en un vector de 1s de longitud suficiente para permitir el cálculo de proceder, algo conocido como reciclaje en R-hablar.

A veces, puede que tenga que iterar sobre un objeto con un lazo o usando uno de la familia s|l|t|apply(), pero más a menudo se encuentra una función que funciona para un vector de la totalidad de los datos de una sola vez. Esta es una de las ventajas de R con respecto a otros lenguajes de programación, pero no se requiere para obtener su cabeza en vectorizado modo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top