Как использовать функцию while () для вычисления матрицы по одной строке за раз, пока я не найду индекс последней строки в последнем столбце, который достигнет <0 - PullRequest
2 голосов
/ 06 ноября 2010

отредактировано для ясности -

Мне интересно найти нулевую точку многомерной функции автокорреляции.

Я могу сгенерировать матрицу автокорреляции из моих данных, используя

acm <- autocorr(x, 1:10)

Однако полная матрица может быть порядка 20 x 5000, и это требует больших вычислительных затрат.

Поэтому я хотел бы рассчитывать только 1 или n строк за раз,

Вот шаги, которые я хотел бы предпринять

  1. вычислить первую строку в матрице
  2. , в то время как (любой столбец имеет все положительные значения) вычислить и добавитьследующая строка матрицы для уже вычисленных строк
  3. идентифицирует индекс строки последнего столбца, чтобы достичь нуля

Если это полная матрица:

acm <- cbind( c(10, 9, 8, 7, 6, 5, 4, 3, 1, -1),
              c(10, 8, 6, 5, 3, 1, -1, 1, -1, 0 ))

Мне нужна функция, которая будет возвращать 10, потому что первый столбец является последним, который достигает отрицательного значения.Если бы я сначала вычислил полную матрицу, было бы достаточно следующего:

max(which(apply(acm, 2, min)))

Но я хочу избежать вычисления большего количества acm, чем необходимо, например, потому что часто только 1 или небольшая часть строк необходимы длярасчет.

Ответы [ 3 ]

1 голос
/ 08 ноября 2010

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

find.point <- function(x){
    tt <- rep(F,ncol(x))         # control vector tt

    for (i in 1:nrow(x)){
        tt[which(x[i,]<0)] <- T  # check which columns have negative value
        if(all(tt)) break        # if all have reached negative, get out of loop
    }
    i                          # return index
}

Выходная информация такая же, как на вкладыше

max(apply(acm<0,2,function(x) match(T,x)))

К чему вы пытались обратиться в своем вопросе, я верю. Я действительно не понимаю, откуда ваша проблема с производительностью. Это зависит от того, есть ли у вас 5000 столбцов или 5000 строк. В любом случае, даже если набор данных в десять раз больше, для меня расчеты выполняются в течение секунды с использованием oneliner:

Тайминги:

> acm <- matrix(rep(seq.int(5000,-5999),100),ncol=22)

> dim(acm)
[1] 50000    22

> system.time(max(apply(acm<0,2,function(x) match(T,x))))
   user  system elapsed 
   0.05    0.00    0.05 

> system.time(find.point(acm))
   user  system elapsed 
   0.05    0.00    0.05 

Тем не менее, время значительно улучшено с помощью функции oneliner, когда у вас много столбцов:

> acm <- matrix(rep(seq.int(5000,-5999),100),ncol=50000)

> dim(acm)
[1]    22 50000

> system.time(max(apply(acm<0,2,function(x) match(T,x))))
   user  system elapsed 
   0.85    0.01    0.86 

> system.time(find.point(acm))
   user  system elapsed 
   0.03    0.00    0.04 

Черт, вы заставили меня придумать решение для цикла, которое работает быстрее, чем простой. Прикольный вопрос!

0 голосов
/ 06 ноября 2010

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

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

matrix(rep(1:10,4),nrow=10,ncol=4)

Затем я запускаю "tapply" для исходной матрицы с матрицей группировки.Это подставляет матрицу так, что каждый вектор строки передается в функцию:

function(x) { return( x[which(x<0)] ) }

, которая просто возвращает все значения, где значение меньше нуля на строку.

> a
            [,1]       [,2]       [,3]       [,4]
 [1,]  0.5341781 -0.9263866 -0.5380141 -1.2453310
 [2,]  0.2931630  1.0490300  0.8127472  0.2473263
 [3,]  1.0936143 -0.3399709  1.8199833  1.0053080
 [4,]  1.0002433  0.2002659  1.7730118  1.7578414
 [5,]  0.8116914  0.9371518  0.8727981  1.4236349
 [6,] -0.1127914  1.1563594  1.0331311  0.7658510
 [7,] -0.5423493  1.8905533 -0.8121652  0.1355076
 [8,] -1.6589310  0.4081290  0.3560005  1.6043205
 [9,]  1.8760435  0.8826245  1.4457357  0.7561550
[10,] -0.8503400  0.2302597  0.5838986  0.1252952
> matrix(rep(1:10,4),nrow=10,ncol=4)
      [,1] [,2] [,3] [,4]
 [1,]    1    1    1    1
 [2,]    2    2    2    2
 [3,]    3    3    3    3
 [4,]    4    4    4    4
 [5,]    5    5    5    5
 [6,]    6    6    6    6
 [7,]    7    7    7    7
 [8,]    8    8    8    8
 [9,]    9    9    9    9
[10,]   10   10   10   10
> tapply(a, matrix(rep(1:10,4),nrow=10,ncol=4), function(x) { return(x[which(x<0)])})
$`1`
[1] -0.9263866 -0.5380141 -1.2453310

$`2`
numeric(0)

$`3`
[1] -0.3399709

$`4`
numeric(0)

$`5`
numeric(0)

$`6`
[1] -0.1127914

$`7`
[1] -0.5423493 -0.8121652

$`8`
[1] -1.658931

$`9`
numeric(0)

$`10`
[1] -0.85034
0 голосов
/ 06 ноября 2010

Я точно не знаю, что делает ваша функция, но отвечаю на вопрос «Как найти последнюю строку динамически генерируемой матрицы, в которой значение столбца становится меньше нуля?»:

findlastzero = function(mat){
     apply(mat<0, 2, function(x)tail(which(x),1 ))
   }

set.seed(1)
a <- cbind(rnorm(10), rnorm(10), rnorm(10), rnorm(10)) + 0.5

a

            [,1]       [,2]        [,3]        [,4]
 [1,] -0.1264538  2.0117812  1.41897737  1.85867955
 [2,]  0.6836433  0.8898432  1.28213630  0.39721227
 [3,] -0.3356286 -0.1212406  0.57456498  0.88767161
 [4,]  2.0952808 -1.7146999 -1.48935170  0.44619496
 [5,]  0.8295078  1.6249309  1.11982575 -0.87705956
 [6,] -0.3204684  0.4550664  0.44387126  0.08500544
 [7,]  0.9874291  0.4838097  0.34420449  0.10571005
 [8,]  1.2383247  1.4438362 -0.97075238  0.44068660
 [9,]  1.0757814  1.3212212  0.02184994  1.60002537
[10,]  0.1946116  1.0939013  0.91794156  1.26317575


findlastzero(a)
[1] 6 4 8 5

Не уверен, что это то, что вы просите, однако ..

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...