Domanda

Ho un dataframe "foo" simile a questo

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.

Vorrei aggiungere a questo dataframe una nuova colonna che mostra me il valore di densità del ritorno corrispondente. Ho provato:

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

Ma non ha funzionato. Ho davvero difficoltà ad applicare una "funzione" per ogni riga. Ma forse c'è anche un altro modo per farlo, non si usa densità ()?

Quello che in sostanza vorrei fare è quello di estrarre i valori di densità a muro da densità () per i ritorni in foo. Se io faccio solo plot (densità (foo $ Return)) mi dà la curva, però mi piacerebbe avere i valori di densità attaccati ai rendimenti.

@Joris:

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

calcola qualcosa, tuttavia sembra tornare valori di densità sbagliati.

Grazie per avermi aiutato! Dani

È stato utile?

Soluzione

Il secondo pensiero, dimenticare la funzione di densità, mi resi conto che cosa si voleva fare. La maggior parte delle funzioni di densità restituiscono una griglia, in modo da non ti danno la valutazione nei punti esatti. Se si vuole che, ad esempio, è possibile utilizzare il pacchetto 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")

Se il numero di valori diversi non è così grande, è possibile utilizzare ave ():

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

Se lo scopo è quello di trama una funzione di densità, non c'è bisogno di calcolarlo come avete fatto. Proprio l'uso

plot(density(foo$Return))

In alternativa, per aggiungere un istogramma sotto (mente l'opzione freq=F)

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

Altri suggerimenti

Un'alternativa al sm.density è quello di valutare la densità su una griglia più fine di default, e l'uso approx o approxfun per dare i valori interpolati della densità alla Returns che si desidera. Ecco un esempio con dati fittizi:

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

A questo punto, abbiamo potuto usare approx() interpolare i componenti x e y della densità restituito, ma io preferisco approxfun() che fa la stessa cosa, ma restituisce una funzione che si può utilizzare per fare l'interpolazione. In primo luogo, generare la funzione di interpolazione:

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

Ora è possibile utilizzare BAR() per restituire la densità interpolato in qualsiasi momento lo si desidera, ad esempio, per la prima Returns:

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

Per completare l'esempio, aggiungere la densità per ogni dato in 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

Per vedere quanto bene l'interpolazione sta facendo, siamo in grado di tracciare la densità e la versione interpolata e confrontare. Nota dobbiamo ordinare Returns perché per ottenere l'effetto che vogliamo, esigenze lines per vedere i dati in aumentando ordine:

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

che dà qualcosa di simile a questo: Densità (in nero) e la versione interpolato (in rosso)

Fino a quando la densità è valutata a sufficientemente fine una serie di punti (512 * 8 nell'esempio di cui sopra) non dovreste avere alcun problema e sarà spinto difficile capire la differenza tra la versione interpolata e la cosa reale . Se si dispone di "buchi" nei valori del vostro Returns allora si potrebbe scoprire che, come lines() unisce solo i punti che chiedergli di tracciare, che segmenti di linee rette potrebbero non seguire la densità di nero nelle posizioni delle lacune. Questo è solo un artefatto delle lacune e come funziona lines(), non è un problema con l'interpolazione.

Se ignoriamo il problema density, che @Joris sapientemente risposte, non sembrano aver compreso come impostare un ciclo. Quello che si sta tornando dal loop è il valore di NULL. Questo è il valore che viene inserito nella foo$density e che non sarà non lavoro perché è il NULL, che significa che è un componente vuoto, cioè non esiste per quanto R è interessato. Vedere ?'for' per ulteriori dettagli.

> 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

Se si desidera inserire il valore di ritorno per ogni iterazione del ciclo, è necessario effettuare l'assegnazione all'interno il ciclo, e questo significa che si dovrebbe pre-allocare lo spazio di archiviazione prima di entrare nel ciclo , per esempio il loop di cui sopra, se volevamo avere i + 1 per i in 1, ..., 10, abbiamo potuto fare questo:

> 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

Naturalmente, non farebbe un tale calcolo come questo tramite un ciclo, perché R è vettorializzare e lavorerà con i vettori di numeri, piuttosto che dover codice di ogni elemento di calcolo per elemento come si potrebbe in C o altri linguaggi di programmazione .

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

Si noti che R è trasformata 1 in un vettore di 1s di lunghezza sufficiente per permettere il calcolo di procedere, qualcosa conosciuto come riciclo in R-parlare.

A volte, si potrebbe aver bisogno di iterare su un oggetto con un loop o utilizzando uno della famiglia s|l|t|apply(), ma più spesso troverete una funzione che lavori per un intero vettore di dati in una sola volta. Questo è uno dei vantaggi di R rispetto ad altri linguaggi di programmazione, ma non si richiede di ottenere la testa in vettorizzati Modalità.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top