我有10个股票回报的矩阵100天(100行和10列)。我正在对它应用以下操作。
我使用的循环在较大的数据集上需要很长时间。我确信这可以通过数组操作进行简化。
1)选择每行中的前3位和后3位值,并将值的索引存储在“选择”矩阵(也是100x10向量)中作为“1”
Ret=array(rnorm(1000),dim=c(100,10))
select=array(rep(0,1000),dim=c(100,10))
Ret.top <- t(apply(Ret, 1, order, decreasing=T)[1:3,])
Ret.bottom <- t(apply(Ret, 1, order, decreasing=F)[1:3,])
for( i in 1:dim(Ret)[1])
{
select[i,Ret.top[i,]]=1
select[i,Ret.bottom[i,]]=1
}
2)然后我有一个信号向量,每天为所有股票计算(信号矩阵,100乘10)。对于上述步骤中的选定股票,我检查信号并选择具有2个最高信号的股票以及具有2个最低信号的股票,并将其指数存储在长短矩阵中。 (最高信号为+1,最低信号为-1)
signal=array(rnorm(1000),dim=c(100,10))
longshort= array(rep(0,1000),dim=c(100,10))
for( i in 1:dim(Ret)[1])
{
x=order(signal[which(select[i,]==1)],decreasing=T)[1:2]
longshort[i,x]=1;
y=order(signal[which(select[i,]==1)],decreasing=F)[1:2]
longshort[i,y]=-1
}
非常感谢将这些循环转换为数组操作的任何帮助!
答案 0 :(得分:1)
ifelse
将完成这项工作。
Ret.top <- t(apply(Ret, 1, rank))
select= ifelse(Ret.top <= 3 | Ret.top >=8,1,0)
longshort <-ifelse(Ret.top <= 2,-1,
ifelse(Ret.top >= 9,+1,0) )
BTW,OP,我认为你在这些方面犯了一个错误。您只选择前三行,而不是排名最高的行。
Ret.top <- t(apply(Ret, 1, order, decreasing=T)[1:3,])
Ret.bottom <- t(apply(Ret, 1, order, decreasing=F)[1:3,])
答案 1 :(得分:0)
嗯,这是我到目前为止所得到的:
Ret.ord <- apply(Ret, 1, order) # ascending order
select2 <- t(apply(Ret.ord, 2, function(x) { y<-integer(10); y[x[c(1:3,8:10)]] <- 1; y}))
all.equal(select, select2) # same as yours
答案 2 :(得分:0)
您可以定义一个函数,为单个行执行该操作,然后apply
为每行。实际上,您可以对这两个问题使用相同的功能。
top_and_bottom <- function(x, k=3, ...) {
o <- rank(x, ...)
n <- length(x)
ifelse( o <= k, -1, ifelse( o >= n-k+1, 1, 0 ) )
}
n <- 10
k <- 7
Ret <- array(rnorm(k*n),dim=c(n,k))
select <- t(apply( Ret, 1, top_and_bottom, 3 ))
select <- abs(select)
signal <- array(rnorm(k*n),dim=c(n,k))
longshort <- t(apply(signal, 1, top_and_bottom, 2))
编辑:我误解了问题的第二部分。 以下内容应该更接近您想要的内容。
longshort <- t(apply(
# Replace the non-selected values by the median,
# to ensure they are not in the top or bottom.
ifelse( select==1, t(signal), apply(t(signal), 1, median) ),
1,
top_and_bottom, 2
))