4

このようなデータフレーム「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() を使用しない別の方法があるのではないでしょうか?

私が本質的にやりたいことは、density() から foo の戻り値に適合した密度値を抽出することです。plot(density(foo$Return)) を実行すると曲線が得られますが、リターンに密度値を付けたいと思います。

@ヨリス:

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

何かを計算しますが、間違った密度値を返すようです。

助けてくれてありがとう!ダニ

4

4 に答える 4

5

もう一度考えてみると、密度関数のことは忘れて、あなたが何をしたいのか突然わかりました。ほとんどの密度関数はグリッドを返すため、正確なポイントで評価を行わないでください。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")
于 2010-12-20T10:56:54.250 に答える
4

代わりに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()を補間するために使用できますが、同じことを行い、補間を行うために使用できる関数を返す方を好みます。まず、補間関数を生成します。xyapproxfun()

## 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"))

次のようなものが得られます。 密度 (黒) と補間バージョン (赤)

密度が十分に細かい点のセット (上記の例では 512*8) で評価される限り、何の問題もないはずであり、補間されたバージョンと実際のものとの違いを見分けるのは難しいでしょう。の値に「ギャップ」がある場合、プロットするように要求したポイントを結合するだけで、直線セグメントがギャップの位置で黒の密度に従わないことがありますReturns。これは、補間の問題ではなく、lines()ギャップとその仕組みの単なるアーティファクトです。lines()

于 2010-12-20T13:32:01.437 に答える
2

density@Joris が巧みに回答している問題を無視すると、ループの設定方法を理解していないようです。ループから返されるのは valueNULLです。これは挿入される値であり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, i...,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 は、計算を進めるのに十分な長さの s の1ベクトルになっていることに注意してください。これは、R 用語でリサイクルと呼ばれるものです。1

場合によっては、ループまたはファミリの 1 つを使用してオブジェクトを反復処理する必要がある場合がありますがs|l|t|apply()、ほとんどの場合、データのベクトル全体に対して一度に機能する関数を見つけることができます。これは、他のプログラミング言語に対する R の利点の 1 つですが、頭をベクトル化モードにする必要があります。

于 2010-12-20T13:04:54.390 に答える