每个回报的密度值

时间:2010-12-20 10:48:34

标签: r kernel-density

我的数据框“foo”看起来像这样

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.

我想在此数据框中添加一个新列,显示相应返回的密度值。我试过了:

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

但它没有用。我真的很难将“功能”应用到每一行。但也许还有另一种方法可以做到这一点,而不是使用density()?

我基本上想要做的是从Dens()中提取拟合密度值到foo中的回报。如果我只是绘图(密度(foo $ Return))它会给我曲线,但是我希望将密度值附加到返回值。

@Joris:

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

计算某些东西,但似乎返回错误的密度值。

感谢您帮助我! 达尼

4 个答案:

答案 0 :(得分:4)

第二个想法,忘记密度函数,我突然意识到你想做什么。大多数密度函数返回一个网格,因此不要给出精确点的评估。如果您需要,可以使用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")

如果不同值的数量不是那么大,可以使用ave():

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

如果目的是绘图密度函数,则不需要像你那样计算它。只需使用

plot(density(foo$Return))

或者,在下面添加直方图(请注意选项freq=F

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

答案 1 :(得分:4)

sm.density的替代方法是在比默认网格更精细的网格上评估密度,并使用approxapproxfun来提供{{1}处密度的插值} 你要。以下是虚拟数据的示例:

Returns

此时,我们可以使用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)) 来插入返回密度的approx()x组件,但我更喜欢y做同样的事情,但是返回一个函数,然后我们可以用它来进行插值。首先,生成插值函数:

approxfun()

现在,您可以使用## x and y are components of dens, see str(dens) BAR <- with(dens, approxfun(x = x, y = y)) 在您希望的任何位置返回插值密度,例如对于第一个BAR()

Returns

要完成示例,请在> with(foo, BAR(Returns[1])) [1] 0.3268715 中添加每个数据的密度:

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 进行排序,因为为了达到我们想要的效果,Returns需要查看增加顺序中的数据:

lines

这给出了这样的东西: Density (in black) and interpolated version (in red)

只要在足够精细的一组点(上例中为512 * 8)中评估密度,就不应该有任何问题,并且很难说出内插版本和真实内容之间的区别。如果您的plot(dens) with(foo, lines(sort(Returns), BAR(sort(Returns)), col = "red")) 值存在“差距”,那么您可能会发现,因为Returns只是加入您要求它绘制的点,直线段可能不会跟随黑色密度间隙的位置。这只是间隙的假象以及lines()的工作原理,而不是插值的问题。

答案 2 :(得分:2)

如果我们忽略@Joris熟练回答的density问题,您似乎没有掌握如何设置循环。您从循环返回的是值NULL。这是在foo$density中插入的值,并且不会起作用,因为它是NULL,这意味着它是一个空组件,即它不存在,只要R是关心。有关详细信息,请参阅?'for'

> 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

如果要为循环的每次迭代插入返回值,则必须在循环中执行 赋值,这意味着在进入循环之前应预先分配存储空间,例如上面的循环,如果我们希望{1}} i + 1在1,...,10中,我们可以这样做:

i

当然,你不会通过循环进行这样的计算,因为R是矢量化的并且可以使用数字向量,而不是像C或其他编程语言那样按元素编码每个计算元素。

> 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

请注意,R已将> bar <- 1:10 + 1 > bar [1] 2 3 4 5 6 7 8 9 10 11 变为1的足够长度的向量,以允许计算继续进行,在R-speak中称为 recycle 。< / p>

有时,您可能需要使用循环或使用1系列之一迭代对象,但大多数情况下,您会发现一个函数可以一次性处理整个数据向量。这是R优于其他编程语言的优势之一,但确实需要您进入矢量化模式。

答案 3 :(得分:0)

使用它来获取密度值。

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