How to vectorize: set a value based on last time a binary vector was 1
I have another开发者_C百科 R beginner question...
How can I vectorize (avoid for loop in) following code:
# algorithm for getting entry prices (when signal > 0): look back from current
# position until you find first signal > 0,
# `mktdataclose` at that time is entry price
# `entryPrices` is an xts object representing entry prices
# if entryPrices are not available (is.null == TRUE) then wee need to reconstruct
# them from signal (xts object with 1 when entry signal triggered and 0
# otherwise) and close prices available in mktdataclose (an xts object with the
# same length as signal and same dates just that it represents closing prices)
EntryPrices <- entryPrices
if (is.null(EntryPrices)) {
# get entryprices as close prices on buy signal
EntryPrices <- ifelse(signal > 0, mktdataclose, 0)
entryPrice <- 0
for (i in 1:NROW(signal)) {
if (signal[i] > 0) entryPrice <- mktdataclose[i]
EntryPrices[i] <- entryPrice
}
}
I am stuck at thinking SAS data step way and desperatley looking for retain etc. Where can I find some simple exaples in order to understand sapply etc (r help via ?sapply is unfortunately to complicated for me... :( )
Thank you for your kind help.
Best, Samo.
If I understood correctly, your problem is: you have two vectors signal
and mktdataclose
of length n
, and you want to create a new vector EntryPrices
of length n
such that mktdataclose[i]
is the value of mktdataclose
the last time signal
was 1 at or before time i
. You can do this without a for loop, using cummax
, an often unexpectedly useful function (Note that this question is similar in flavor to some of your earlier questions, which were similarly solved using this function and cumsum
). Here we go, using Gavin's data:
set.seed(123)
signal <- sample(0:1, 10, replace = TRUE)
mktdataclose <- runif(10, 1, 10)
Our problem is really to convert the signal
vector into a vector of the appropriate indices:
indices <- cummax( seq_along(signal) * signal)
This is exactly the indices
we want, except for the 0. Now we set EntryPrices
by extracting the values at the non-zero indices
from mktdataclose
:
EntryPrices <- c( rep(0, sum(indices==0)), mktdataclose[ indices ])
> cbind(signal, indices, mktdataclose, EntryPrices)
signal indices mktdataclose EntryPrices
[1,] 0 0 9.611500 0.000000
[2,] 1 2 5.080007 5.080007
[3,] 0 2 7.098136 5.080007
[4,] 1 4 6.153701 6.153701
[5,] 1 5 1.926322 1.926322
[6,] 0 5 9.098425 1.926322
[7,] 1 7 3.214790 3.214790
[8,] 1 8 1.378536 1.378536
[9,] 1 9 3.951286 3.951286
[10,] 0 9 9.590533 3.951286
since signal is 0 and 1 i presume you can vectorize with:
EntryPrices * signal
Here's another solution that you may find more straight-forward. I'm using Prasad's psudo-data.
> EntryPrices <- ifelse(signal > 0, mktdataclose, NA)
> EntryPrices <- na.locf(EntryPrices, na.rm=FALSE)
> cbind(signal,mktdataclose,EntryPrices)
signal mktdataclose EntryPrices
[1,] 0 9.611500 NA
[2,] 1 5.080007 5.080007
[3,] 0 7.098136 5.080007
[4,] 1 6.153701 6.153701
[5,] 1 1.926322 1.926322
[6,] 0 9.098425 1.926322
[7,] 1 3.214790 3.214790
[8,] 1 1.378536 1.378536
[9,] 1 3.951286 3.951286
[10,] 0 9.590533 3.951286
精彩评论