Избегание циклов, но сохранение информации об индексе - PullRequest
2 голосов
/ 01 мая 2011

Я работаю с некоторыми графоподобными данными, в основном собранными в векторах или списках.
Большую часть времени мне нужно проверять векторы / списки по заданным индексам и выполнять некоторую логику, чтобы определить результирующее значение для текущего элемента.

Чтобы быть более точным, рассмотрим такой фрагмент кода:

for (i in 1:(length1 - 1))
    for (j in (i + 1):length2)
        for (k in 1:length3) {
            d1 <- data[i, k]
            d2 <- data[j, k]
            if (d1 != d2)
                otherData[i, j, k] <- list(c(min(d1, d2), max(d1, d2)))
            else
                otherData[i, j, k] <- list(c(1, 1))
        }

Мой вопрос:
- Было бы хорошим решением:

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

Пример кода (проще, без связи с кодом выше):

someFunc <- function(data) {
    n <- length(data)
    f <- function(i) {
        return (doSthWith(data[i], i))
        # do some logic with both the data and the index
    }
    return (sapply(1:n, f))
}

Другое решение, которое я придумал, - создать data.frame и сделатьиндексирует часть данных, поэтому функции lapply в основном будут иметь индексы и во входной строке.

Я буду очень признателен за ваши мысли об этих подходах.

1 Ответ

1 голос
/ 01 мая 2011

Ну, вы можете сделать векторизованную индексацию, которая должна дать вам шанс значительно ускориться. В общем, вместо:

for(a in A) for(b in B) something(x[a,b])

Вы можете сделать:

something_vectorized(x[as.matrix(expand.grid(A,B))])

* apply - это, по сути, обертки циклов, поэтому вы получите максимально чистый код, преобразовав в них циклы.

РЕДАКТИРОВАТЬ: Маленькая иллюстрация, чтобы дополнить комментарий:

> system.time(replicate(100,sum(sapply(1:1000,function(x) x^2))))
   user  system elapsed 
  0.385   0.001   0.388 
> system.time(replicate(100,sum((1:1000)^2)))
   user  system elapsed 
  0.002   0.001   0.003
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...