Earlier today I wrote up a fold for somebody else for retrieving the
last N elements of a sequence. That's the non-trivial bit:
http://lpaste.net/103997
The relevant part is:
lastN :: Int -> Fold a (Seq a)
lastN n = Fold step begin done
where
step s a = (if (S.length s < n) then s else S.drop 1 s) |> a
begin = S.empty
done = id
Once you have that, it's as simple as applying a non-streaming average
to that:
fmap (\xs -> sum xs / genericLength xs) (lastN n)
There's no point using a streaming average for this final step since for
a moving window average you have to use O(N) space no matter what
approach you use. This is why I prefer exponentially-weighted moving
averages. Like Tony mentioned, they are much easier to write and they
run in O(1) space.
On 05/11/2014 06:42 PM, Tony Day wrote:
*Spoiler Alert* if you want to have a stab at the fold yourself.
I've been meaning to code this up for a while ...
import Control.Applicative
import Control.Foldl as L
import Data.Sequence (ViewR(EmptyR, (:>)), (<|))
import qualified Data.Sequence as Seq
maybeSum :: Fold (Maybe Double) (Maybe Double)
maybeSum = Fold (liftA2 (+)) (Just 0) id
sma :: Int -> Fold Double Double
sma n = L.Fold step begin done
where
begin = Seq.replicate n Nothing
av x = liftA2 (/) (L.fold maybeSum x) (pure (fromIntegral n))
done x = case av x of
Nothing -> 0/0
Just x' -> x'
step x a = Just a <| pop x
pop x = case Seq.viewr x of
EmptyR -> x
x'' :> _ -> x''
λ> L.scan (sma 3) [1..10]
[NaN,NaN,NaN,2.0,3.0,4.0,5.0,6.0,7.0,8.0,9.0]
or
λ> runEffect $ each [1..5] >-> L.purely P.scan (sma 2) >-> P.print
NaN
NaN
1.5
2.5
3.5
4.5
I would rate this as hard, especially in comparison to the
exponentially-weighted version. Is this category theory suggesting
that a sliding window is the wrong way to go about moving averages,
contrary to intuition?
On Thursday, March 6, 2014 2:01:23 AM UTC+10, Alex Rozenshteyn wrote:
I feel like I must be missing something rather basic, but I have
been trying to figure out how to use pipes to compute a moving
average of a stream of numbers. I've written code to do the EWMA,
but I can't figure out how to do the sliding window. It doesn't
help that I'm a bit of a pipes beginner.
Advice is welcome and appreciated.
Thank you.
--
You received this message because you are subscribed to the Google
Groups "Haskell Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to [email protected]
<mailto:[email protected]>.
To post to this group, send email to [email protected]
<mailto:[email protected]>.
--
You received this message because you are subscribed to the Google Groups "Haskell
Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].