我有一个像这样的数据框“ 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

但这没用。我真的很难在每行中应用“函数”。但是,也许还有另一种方法可以做到,而不是使用密度()?

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

@Joris:

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

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

谢谢您帮助我!丹妮

有帮助吗?

解决方案

第二次思考,忘记了密度功能,我突然意识到您想做什么。大多数密度功能返回网格,因此请勿在确切点中给您评估。如果需要,可以使用 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")

其他提示

替代方案 sm.density 是评估比默认网格较细的网格的密度,并使用 approx 或者 approxfun 给出密度的插值值 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() 插入 xy 返回密度的组件,但我更喜欢 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 需要查看数据 增加 命令:

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

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

只要在足够细的一组点上评估密度(在上面的示例中为512*8),您就不应该遇到任何问题,并且很难说出插值版本与真实事物之间的差异。如果您的值中有“差距” Returns 然后,您可能会发现 lines() 只需加入您要求它绘制的要点,直线段可能不会遵循间隙位置的黑色密度。这只是差距的人工制品以及如何 lines() 作品,插值不是问题。

如果我们忽略了 density @Joris专业回答的问题,您似乎没有掌握如何设置循环。您从循环中返回的是值 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

如果要插入循环的每次迭代的返回值,则必须进行分配 里面 循环,这意味着您应该在进入循环之前将存储空间分配给存储空间,例如,如果我们想拥有上述循环 i + 1 为了 i 在1,...,10中,我们可以做到这一点:

> 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被矢量化,并且会与数字向量一起使用,而不是像在C或其他编程语言中那样按元素编码每个计算元素。

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

请注意R已转过身 1 进入 1足够长的s可以进行计算,这就是所谓的 回收 在r-steak中。

有时,您可能需要在一个循环或使用其中一个的物体上迭代对象 s|l|t|apply() 一家人,但通常您会发现一个适用于整个数据向量的函数。这是R比其他编程语言的优点之一,但确实要求您进入 矢量化 模式。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top