Чтобы пояснить мои замечания в колонке комментариев, предположим, что у нас есть dfmat
как список матриц. Почти всегда легче работать со списком матриц, чем с одной большой именованной матрицей. Также, если вы хотите полностью векторизовать приведенное здесь решение, вы можете получить блочную диагональную матрицу, используя bdiag
из пакета Matrix
, который действует со списками.
set.seed(1)
dfarray=array(rnorm(5*3*14,0,1),dim=c(3,14,5))
# dfmats as a list of matrices
dfmats <- lapply(1:3, function(i)matrix(rnorm(13*14), nrow=13))
Умножение на iota
равно colSums
или rowSums
, поэтому мы можем упростить операцию, как в f
.
f <- function(Xbeta) rowSums(Xbeta / matrix(colSums(Xbeta), nrow=nrow(Xbeta), ncol=ncol(Xbeta), byrow=T)) / ncol(Xbeta)
#profits is written as a function for benchmarking
#cost and p are ignored as they can be easily added back in.
profits <- function(){
Xbetas <- lapply(seq_len(dim(dfarray)[1]), function(i) exp(dfmats[[i]] %*% dfarray[i,,]))
Eprobs <- lapply(Xbetas, f)
unlist(Eprobs)
}
И твой подход
profits1 <- function(){
profit=numeric(0)
for(i in 1:dim(dfarray)[1]){
j=13
beta = dfarray[i,,]
Xt = dfmat [which(dfmat [,'unit']==i),1:14] #this takes a set of 13, Xt is 13x14
Xbeta = exp( Xt %*% beta )
iota = c(rep(1, j))
denom = iota%*%Xbeta
deno <- colSums(Xbeta)
s <- iota%*%denom
Prob = (Xbeta/ s)
Eprob = rowSums(Prob)/dim(dfarray)[3] #the 100 coming from the last dim of array
profit = c(profit,Eprob)
}
return(profit)
}
dfmat <- do.call(rbind, dfmats)
dfmat <- cbind(dfmat,rep(1:3, each=13))
colnames(dfmat)[15]='unit'
Убедитесь, что они дают одинаковые результаты
all.equal(profits(), profits1())
[1] TRUE
Контрольный показатель
Я запустил это на экземпляре AWS EC2 free-tie, доступ к которому можно получить через http://www.louisaslett.com/RStudio_AMI/ < / а>.
dfarray=array(rnorm(100*10000*14,0,1),dim=c(10000,14,100))
dfmats <- lapply(1:10000, function(i)matrix(rnorm(13*14), nrow=13))
Из исходной конструкции вы можете преобразовать dfmat
в список dfmats
как dfmats <- lapply(1:3, function(i)dfmat[which(dfmat [,'unit']==i),1:14])
, но это очень затратное преобразование. Создание dfmat
из dfmats
обходится дешевле.
dfmat <- do.call(rbind, dfmats)
dfmat <- cbind(dfmat,rep(1:10000, each=13))
colnames(dfmat)[15]='unit'
Обратите внимание на исключительное ускорение использования list
и опасность ужасной стоимости поиска имени.
system.time(a1 <- profits1())
# user system elapsed
#250.885 4.442 255.394
system.time(a <- profits())
# user system elapsed
# 2.717 0.429 3.167
all.equal(a, a1)
#[1] TRUE
PS: Я заметил, что вы задали несколько вопросов, потенциально связанных с этим вопросом, на все ответили. Я буду рад, если вы расскажете, как вы успешно применили их.
person
Khashaa
schedule
15.03.2015
dfmat
также в трехмерном массиве? - person cryo111   schedule 09.03.2015tensorA
. Он предоставляет функциюmul.tensor
. Я предполагаю, что вам нужно использовать аргументby
в этой функции, чтобы перебрать ваш индексi
. - person cryo111   schedule 09.03.2015mul.tensor(X,i=c(),Y,j=i,by=NULL)
.X
иY
будут вашими трехмерными массивами (в этом случае тензорными объектами). С помощьюi
иj
вы можете определить индексы, которые используются для умножения матриц, а аргументby
- это ваша переменная цикла (i
в вашем случае). - person cryo111   schedule 09.03.2015Rcpp
и _2 _... - person cryo111   schedule 09.03.2015Mul.tensor
должно быть быстрее. Да,Rcpp
использует C ++. Это займет некоторое время, но вместе сRcppArmadillo
это действительно полезно, если вы делаете много вещей, которые нелегко векторизовать. - person cryo111   schedule 10.03.2015mul.tensor
- вроде не быстрее цикла. Не ожидал этого. - person cryo111   schedule 10.03.2015sum(Eprob)
равно 1, поэтому я немного озадачен тем, чего вы пытаетесь достичь. - person Khashaa   schedule 10.03.2015dfmat
как именованную матрицу, а не список матриц? - person Khashaa   schedule 10.03.2015Xt = dfmat [which(dfmat [,'unit']==i),]
. Если вместо этого вы сохранитеdfmat
как список матриц, а затем получите доступ к его элементам какXt = dfmat [[i]]
, это будет в несколько раз быстрее. - person Khashaa   schedule 10.03.2015