2016-07-21 4 views
0
require(quantmod) 
require(TTR) 

iris2 <- iris[1:4] 
b=NULL 
for (i in 1:ncol(iris2)){ 
for (j in 1:ncol(iris2)){ 
a<- runCor(iris2[,i],iris2[,j],n=21) 
b<-cbind(b,a)}} 

Я хочу рассчитать скользящую корреляцию разных столбцов в пределах кадра данных и хранить данные отдельно по столбцу. Хотя вышеприведенный код хранит данные в переменной b, это не так полезно, как просто сбрасывает все результаты. Я хотел бы иметь возможность создавать различные данные для каждого i.Как хранить данные из цикла for внутри цикла for? (корреляция качения в r)

В этом случае, поскольку у меня есть 4 столбца, в конечном итоге я хочу, чтобы 4 кадра данных, каждая из которых содержала 4 столбца, показывающие скользящие корреляции, то есть df1 = corr col 1 vs col 1,2,3,4, df2 = corr col 2 vs col 1,2,3,4 ... и т. д.)

Я думал об использовании lapply или rollapply, но столкнулся с той же проблемой.

d=NULL 
for (i in 1:ncol(iris2)) 
for (j in 1:ncol(iris2)) 
{c<-rollapply(iris2, 21 ,function(x) cor(x[,i],x[,j]), by.column=FALSE) 
d<-cbind(d,c)} 

Действительно оценен любой вход.

+0

попробуйте 'foreach' цикл или' mapply' над вектором индекса. Он предоставит вам список списков списка DF. Вложено 'i', затем' j', а затем 'c & d' – Adam

+0

. Никогда не рекомендуется использовать cbind в цикле for. Гораздо лучше использовать список с предопределенной длиной, чтобы избежать чрезмерного копирования в памяти. –

ответ

2

Если вы хотите сохранить расширенный цикл, как насчет списка данных?

e <- list(length = length(ncol(iris2))) 

for (i in 1:ncol(iris2)) { 
    d <- matrix(0, nrow = length(iris2[,1]), ncol = length(iris2[1,])) 
    for (j in 1:ncol(iris2)) { 
     d[,j]<- runCor(iris2[,i],iris2[,j],n=21) 
    } 
e[[i]] <- d 
} 

Это также хорошая идея, чтобы выделить объем пространства, который вы хотите с заполнителями и поместить элементы в этом пространстве, а не использовать rbind или cbind.

+0

Спасибо за предложение. Не думал об этом, и он отлично работает. Но проблема в том, что фактические данные, которые я запускаю, имеют более 100 столбцов, и кажется, что для запуска кода требуется более 20 минут ... Я просто хочу видеть скользящую корреляцию данных со всеми остальными, так как я кратко упомянутый в моем вопросе. Будет ли какой-нибудь способ сделать его более эффективным? Еще раз спасибо. – sh2657

+0

@ sh2657 Ваш комментарий кажется отрезанным. –

+0

Извините, что я случайно нажал enter и редактировал его. Должно быть хорошо сейчас. – sh2657

2

Хотя не хорошая практика, чтобы создать dataframes на лету в R (вы должны предпочитать положить их в списке, как и в других ответов), способ сделать так, чтобы использовать assign и get функции.

for (i in 1:ncol(iris2)) { 
    for (j in 1:ncol(iris2)){ 
     c <- runCor(iris2[,i],iris2[,j],n=21) 

     # Assign 'c' to the name df1, df2... 
     assign(paste0("df", i), c) 
     } 
} 

# to have access to the dataframe: 
get("df1") 

# or inside a loop 
get(paste0("df", i)) 
1

Поскольку вы заявили, что ваши вычисления были медленными, я хотел бы предоставить вам параллельное решение. Если у вас есть современный компьютер, он, вероятно, имеет 2 ядра, если не 4 (или больше!). Вы можете легко проверить это с помощью:

require(parallel) # for parallelization 
detectCores() 

Теперь код:

require(quantmod) 
require(TTR) 

iris2 <- iris[,1:4] 

распараллеливания требует функции и переменные будут помещены в специальную среду, которая создается и разрушается с каждым процессом. Это означает, что для определения переменных и функций должна быть создана функция-обертка.

wrapper <- function(data, n) { 
    # variables placed into environment 
    force(data) 
    force(n) 

    # functions placed into environment 
    # same inner loop written in earlier answer 
    runcor <- function(data, n, i) { 
    d <- matrix(0, nrow = length(data[,1]), ncol = length(data[1,])) 
    for (j in 1:ncol(data)) { 
     d[,i] <- TTR::runCor(data[,i], data[,j], n = n) 
    } 
    return(d) 
    } 

    # call function to loop over iterator i 
    worker <- function(i) { 
    runcor(data, n, i) 
    } 

    return(worker) 
} 

Теперь создайте кластер на локальном компьютере. Это позволяет работать с несколькими ядрами отдельно.

parallelcluster <- makeCluster(parallel::detectCores()) 
models <- parallel::parLapply(parallelcluster, 1:ncol(iris2), 
           wrapper(data = iris2, n = 21)) 
stopCluster(parallelcluster) 

Остановить и закрыть кластер при завершении.

+0

Ты лучший. Спасибо. – sh2657

Смежные вопросы