I am a ruby novice who would really appreciate some guidance with the
following:
I am trying to calculate a 5 day weighted moving average based on a set
of numbers in a data series. The most recent is given a * 5 weight, the
next * 4 etc etc. with the oldest (the 5th number) * 1.
I am trying to calculate a 5 day weighted moving average based on a set
of numbers in a data series. The most recent is given a * 5 weight, the
next * 4 etc etc. with the oldest (the 5th number) * 1.
Does this help? You will need to handle the edge cases somehow…
$ ri Enumerable#each_cons | cat
--------------------------------------------------- Enumerable#each_cons
each_cons(n) {…}
From Ruby 1.8
Iterates the given block for each array of consecutive <n>
elements.
e.g.:
(1..10).each_cons(3) {|a| p a}
# outputs below
[1, 2, 3]
[2, 3, 4]
[3, 4, 5]
[4, 5, 6]
[5, 6, 7]
[6, 7, 8]
[7, 8, 9]
[8, 9, 10]
I am a ruby novice who would really appreciate some guidance with the
following:
I am trying to calculate a 5 day weighted moving average based on a set
of numbers in a data series. The most recent is given a * 5 weight, the
next * 4 etc etc. with the oldest (the 5th number) * 1.
I am a ruby novice who would really appreciate some guidance with the
following:
I am trying to calculate a 5 day weighted moving average based on a set
of numbers in a data series. The most recent is given a * 5 weight, the
next * 4 etc etc. with the oldest (the 5th number) * 1.
In terms of the main objective, then no, they do not have to be there -
but I think it would help my understanding of what is happening if they
were there…
Ok then lets remove some of the ruby tricks and just make the code work
because as most programmers do I’ve pushed you into the deep end and you
are
looking to keep your feet solidly on the bottom of the pool while still
being able to breathe
Lets try this gist:132285 · GitHub - a little more output at
each
step. It’s different then the first shot I took at it but it’s also much
easier to digest each piece and see what it’s doing.
How would I do that using and amending the original code?
cheers
Are you still wishing to see all the intermediate steps (i.e. the value
of
255, 24.8574 etc etc etc)?
John
Hi John,
thanks for your patience.
In terms of the main objective, then no, they do not have to be there -
but I think it would help my understanding of what is happening if they
were there…
In terms of the main objective, then no, they do not have to be there -
but I think it would help my understanding of what is happening if they
were there…
Ok then lets remove some of the ruby tricks and just make the code work
because as most programmers do I’ve pushed you into the deep end and you
are
looking to keep your feet solidly on the bottom of the pool while still
being able to breathe
Lets try this gist:132285 · GitHub - a little more output at
each
step. It’s different then the first shot I took at it but it’s also much
easier to digest each piece and see what it’s doing.
John
Hi John,
Thanks very much for that. It is very helpful. I think your summary is
pretty accurate of where I am right now - but I will get there!
I think I would find some comments on the code very helpful.
Ok, here we go. The basic idea is to have a single definition of the
weight handling and separate the algorithm from that. That way we can
use the algorithm for whatever weighting schemes we want to apply. I
have “repackaged” the code into a method of module Enumerable which
seems appropriate considering the genericity of the approach.
Basically we have two inputs for the algorithm:
enum of data
weighting scheme
module Enumerable
def weighting(weights)
if block_given?
# input: weights
weights = weights.to_a
# derive the divisor once from the weights because
# it depends on the weights and does not change
# otherwise
div = weights.inject(0){|s,x| s + x}.to_f
# Now iterate through self using a sliding window
# of weights.size elements (this is done by each_cons)
# for each window we calculate the weighted average
# and yield it to the block passed to this method
# Array#zip is used to iterate the weights and the
# sliding window in lock step.
each_cons weights.size do |elements|
sum = 0
elements.zip(weights) {|n,w| sum += n * w}
yield sum / div
end
self
else
# create an Enumerator to allow for chaining.
enum_for(:weighting, weights)
end