Проблема с итерацией по временным рядам в clojure - PullRequest
8 голосов
/ 13 июля 2010

У меня следующая проблема: У меня есть временной ряд с более чем 10000 записями, и я хочу выполнить некоторые вычисления с каждой из них. Это само по себе не будет проблемой, но мне нужно получить последнее вычисленное значение, чтобы получить следующее. Очень простая форма того, что мне нужно, будет выглядеть так:

Val(n) = Val(n-1) + (time-series-entry / 2) (или что-то в этом роде!)

Я понятия не имею, как с этим справиться. Просто делаю что-то вроде этого:

(defn calc-val
  [time-series element]
  (seq (cons (generate-val-element time-series element)
             (calc-val time-series (inc element)))))

не сработает, потому что не может (по крайней мере, я не знаю, как!) Получить последнее вычисленное значение. Тогда я подумал: хорошо, давайте использовать Loop-Recur. Это дало бы мне значение, соответствующее записи временного ряда, НО для следующего, который я должен был бы сделать все вычисления снова. Итерация была бы правильной вещью, но она не работала, потому что у функции были побочные эффекты.

Так что я застрял здесь на этом. Было бы здорово, если бы кто-нибудь дал мне подсказку.

Ответы [ 2 ]

7 голосов
/ 13 июля 2010

Если вам важен только конечный результат, используйте reduce; если вам нужно получить последовательность результатов преобразования каждого значения по очереди (где каждое преобразование зависит от предыдущих), используйте reductions (находится в clojure.contrib.seq-utils в 1.1 и clojure.core в 1.2).

Ниже transform-first-entry делает все, что вы хотите сделать с первой записью (если вам не нужно преобразовывать ее каким-либо образом, вы можете просто пропустить первый аргумент в reduce / reductions и использовать entries вместо (rest entries в качестве последнего аргумента); transform-entry - это функция, которая принимает результат преобразования предыдущей записи и текущей записи (в этом порядке) и выдает результат преобразования для текущей записи.

;;; only care about the final result
(reduce transform-entry
        (transform-first-entry (first series))
        (rest entries))

;;; need to get a seq of intermediate results
(reductions ...arguments as above...)

Обратите внимание, что reductions ленив.

Предполагая, что вы хотите оставить первую запись без изменений и применить свой пример преобразования из текста вопроса к последующим записям, вы можете использовать

(defn transform-entry [prev-transformed current]
  (+ prev-transformed
     (/ current 2)))

как функция сокращения в

(reduce transform-entry series) ; ...or reductions
3 голосов
/ 13 июля 2010

Если вы просто хотите подсказку; изучите использование partition.

чуть больше, чем подсказка

(defn calc-val
  [time-series element]
  (let [p (partition 2 1 time-series)]
    (for [t p]
      (let [first-value (first t)
            second-value (second t)]
        (do whatever you need to here)))))

Хотя это не было проверено, оно должно работать или быть близким к работе :)

Объяснение

(partition n i seq) разделяет seq на части, которые имеют списки длины n (в данном случае 2) с перекрытием i (в данном случае 1), а затем мы перебираем те из них с for что мы хотим с деталями.

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