Я ищу элегантный способ генерации последовательности скользящего среднего последовательности чисел. Надеюсь, что-то более элегантное, чем использование lazy-seqпоследовательность скользящего среднего в Clojure
ответ
без учета эффективности:
(defn average [lst] (/ (reduce + lst) (count lst)))
(defn moving-average [window lst] (map average (partition window 1 lst)))
user> (moving-average 5 '(1 2 3 4 5 6 7 8))
(3 4 5 6)
Если вам это нужно, чтобы быть быстрым, есть некоторые довольно очевидные улучшения, которые будут сделаны! Но он станет менее изящным.
Существует очень похожий вопрос о SO: Calculating the Moving Average of a List. Это более общий - представлен ряд FP-дружественных языков, с принятым ответом с помощью Scala, но есть несколько хороших решений Clojure.
Я разместил my own solution over there. Обратите внимание, что он использует lazy-seq
, но это потому, что я хотел, чтобы он хорошо работал в течение больших периодов (что означает корректировку среднего значения на каждом шаге, а не вычисление отдельного среднего для каждого окна размера = период во входном списке). Посмотрите вокруг этого Q на хорошие решения, которые сделали другой компромисс, в результате чего более короткий код с несколько более декларативным ощущением, который на самом деле работает лучше за очень короткие периоды (хотя и страдает значительным замедлением на более длительные периоды, как и следовало ожидать).
Хорошая идея с ссылкой, спасибо! –
Эта версия немного быстрее, особенно для длинных окон, поскольку она удерживает скользящую сумму и позволяет неоднократно добавлять одни и те же вещи.
Из-за ленивого-SEQ, это также совершенно общий характер и не будет дуть стопка
(defn partialsums [start lst]
(lazy-seq
(if-let [lst (seq lst)]
(cons start (partialsums (+ start (first lst)) (rest lst)))
(list start))))
(defn sliding-window-moving-average [window lst]
(map #(/ % window)
(let [start (apply + (take window lst))
diffseq (map - (drop window lst) lst)]
(partialsums start diffseq))))
;; Чтобы узнать, что он делает:
(sliding-window-moving-average 5 '(1 2 3 4 5 6 7 8 9 10 11))
start = (+ 1 2 3 4 5) = 15
diffseq = - (6 7 8 9 10 11)
(1 2 3 4 5 6 7 8 9 10 11)
= (5 5 5 5 5 5)
(partialsums 15 '(5 5 5 5 5 5)) = (15 20 25 30 35 40 45)
(map #(/ % 5) (20 25 30 35 40 45)) = (3 4 5 6 7 8 9)
;; Пример
(take 20 (sliding-window-moving-average 5 (iterate inc 0)))
О, это очень элегантная идея ... Выполняет примерно то же самое, что и моя скользящая версия окна, но, безусловно, более эстетично. Не могли бы вы разместить его в качестве ответа на этот другой вопрос SO (см. Ссылку в моем ответе здесь)? +1 в любом случае! –
Спасибо за ваши добрые слова. Я разместил его в другом потоке. –
Вместо partialsums
п (что полезно, чтобы увидеть, что происходит), вы можете использовать reductions
в clojure.core:
(defn sliding-window-moving-average [window lst] (map #(/ % window) (let [start (apply + (take window lst)) diffseq (map - (drop window lst) lst)] (reductions + start diffseq))))
- 1. Clojure эквивалент этой функции скользящего среднего Haskell?
- 2. Создание среднего скользящего среднего/окна в таблице
- 3. Расчет скользящего среднего Mongodb
- 4. Расчет неперекрывающегося скользящего среднего
- 5. Ошибка алгоритма скользящего среднего
- 6. Расчет скользящего среднего MySQL?
- 7. DataGridView скользящего среднего значения
- 8. Вычисление скользящего среднего в Haskell
- 9. Расчета скользящего среднего с SQLite
- 10. Вычисления скользящего среднего, за исключением среднего значения в R
- 11. Применение скользящего среднего по группе в R
- 12. Циркуляр скользящего среднего фильтра в LINQ
- 13. Код скользящего среднего в функции R ~ "ma"
- 14. Перечислить последовательность в Clojure?
- 15. Использование скользящего среднего по объединенным значениям
- 16. Расчет экспоненциального скользящего среднего с использованием pandas
- 17. Использование {Ряд предшествующих} для скользящего среднего sql
- 18. Ускорение вычисления WMA (взвешенного скользящего среднего)
- 19. поток безопасный способ вычисления скользящего среднего
- 20. Достичь 3-х дневного скользящего среднего
- 21. скользящего среднего из последних 24 месяцев
- 22. Tensorflow Основы - Вычисление кумулятивный скользящего среднего
- 23. вычисление скользящего среднего с использованием python
- 24. Библиотеки скользящего среднего AutoRegression для C++
- 25. Untuple последовательность Clojure
- 26. Clojure сравнить последовательность в вектор
- 27. последовательность процесса карт в Clojure
- 28. Clojure: ленивая последовательность и «обычная» последовательность
- 29. скользящего среднего в случае недостающего месяца в Teradata
- 30. Замена скользящего среднего для цикла с применением в R
Я ценю краткость и ясность, и в этом случае эффективность просто не вызывает беспокойства, так как это нужно только запустить один раз. –
На самом деле речь идет о самой эффективной ленивой версии для более коротких периодов, поэтому, если вы не ожидаете превысить длину периода около 8, вы должны использовать ее в качестве оптимизации. Если вы собираетесь делать периоды продолжительностью 20, 50 или более, то это станет ужасным по производительности, и вы должны пойти с моей версией. ;-) Кроме того, ознакомьтесь с ведущим ответом Clojure (в целом, на данный момент Джеймсом Каннингемом) в этом старом Q, к которому я привязался к очень изящной однострочной версии этого. :-) –