How to Evaluate the Sum of Values Within Array Blocks

How to evaluate the sum of values within array blocks

Simply reshape splitting each of those two axes into two each with shape (5,20) to form a 4D array and then sum reduce along the axes having the lengths 20, like so -

Z_new = Z.reshape(5,20,5,20).sum(axis=(1,3))

Functionally the same, but potentially faster option with np.einsum -

Z_new = np.einsum('ijkl->ik',Z.reshape(5,20,5,20))

Generic block size

Extending to a generic case -

H,W = 5,5 # block-size
m,n = Z.shape
Z_new = Z.reshape(H,m//H,W,n//W).sum(axis=(1,3))

With einsum that becomes -

Z_new = np.einsum('ijkl->ik',Z.reshape(H,m//H,W,n//W))

To compute average/mean across blocks, use mean instead of sum method.

Generic block size and reduction operation

Extending to use reduction operations that have ufuncs supporting multiple axes parameter with axis for reductions, it would be -

def blockwise_reduction(a, height, width, reduction_func=np.sum):
m,n = a.shape
a4D = a.reshape(height,m//height,width,n//width)
return reduction_func(a4D,axis=(1,3))

Thus, to solve our specific case, it would be :

blockwise_reduction(Z, height=5, width=5)

and for a block-wise average computation, it would be -

blockwise_reduction(Z, height=5, width=5, reduction_func=np.mean)

numpy: efficient summation of values within variably-sized array blocks

Seems like a good fit to use np.add.reduceat to basically sum along rows and then along cols -

def sum_blocks(a, row_sizes, col_sizes):
# Sum rows based on row-sizes
s1 = np.add.reduceat(a,np.r_[0,row_sizes[:-1].cumsum()],axis=0)

# Sum cols from row-summed output based on col-sizes
return np.add.reduceat(s1,np.r_[0,col_sizes[:-1].cumsum()],axis=1)

Sample run -

In [45]: np.random.seed(0)
...: a = np.random.randint(0,9,(4,5))

In [46]: a
Out[46]:
array([[5, 0, 3, 3, 7],
[3, 5, 2, 4, 7],
[6, 8, 8, 1, 6],
[7, 7, 8, 1, 5]])

In [47]: row_sizes = np.array([1,3])
...: col_sizes = np.array([2,3])

In [48]: sum_blocks(a, row_sizes, col_sizes)
Out[48]:
array([[ 5, 13],
[36, 42]])

How to find the sum of an array of numbers

Recommended (reduce with default value)

Array.prototype.reduce can be used to iterate through the array, adding the current element value to the sum of the previous element values.

console.log(  [1, 2, 3, 4].reduce((a, b) => a + b, 0))console.log(  [].reduce((a, b) => a + b, 0))

Sum Blocks of Positive Values in R

We can use rleid to create a group based on the sign of the column i.e. same adjacent sign elements will be a single group and then get the max of the 'cum_profit'

library(dplyr)
dat %>%
group_by(grp = rleid(sign(profit))) %>%
mutate(profit_block2 = max(cum_profit)) %>%
ungroup %>%
select(-grp)

-output

# A tibble: 10 x 5
# profit indic_pos cum_profit profit_block profit_block2
# <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 20 1 20 45 45
# 2 10 1 30 45 45
# 3 5 1 35 45 45
# 4 10 1 45 45 45
# 5 -20 0 0 0 0
# 6 -100 0 0 0 0
# 7 -40 0 0 0 0
# 8 500 1 500 527 527
# 9 27 1 527 527 527
#10 -20 0 0 0 0

Iterate array and sum 1 to each element

You can also do it using recursive functions.
In code below there are 3 simple function,

arsum(ar1,ar2) calculates sum of two array ar1 & ar2

getArr(n,i) returns an array of size n which all of its elements are zero except the one in place i (that's 1)

iterateNBlock(inArray, block) is the start point

calculate(arrayOfArray, block) is the recursive function. when block===0 the input array is result.

in your example when block is 1, you calculate some arrays as result, and when block is 2 you do to all of these arrays, what you did to the first array.

so for block=n you do the same things to the results of when block=n-1.

function arsum(ar1, ar2){
let sum = [];
for(let i=0; i<ar1.length; i++){
sum.push(ar1[i]+ar2[i]);
}
return sum;
}
function getArr(n,i){
let ar = new Array(n).fill(0);
if(i>=0 && i<ar.length)
ar[i]=1;
return ar;
}
function calculate(arrayOfArray, block){
if(block===0)return arrayOfArray;

let n = arrayOfArray[0].length;
let next = [];

for(let i=-1; i<n; i++){
let ar = getArr(n, i);
for(let j=0 ; j<arrayOfArray.length; j++){
next.push(arsum(arrayOfArray[j], ar));
}
}
return calculate(next, block-1);
}
function iterateNBlock(inArray, block){
return calculate([inArray], block);
}

It was a little hard for me to explain it, hope to help you !!!

Mean of NxM elements of array

As of version 1.7, np.mean accepts multiple axes to average. This makes your task easier because you can create as many extra dimensions as you need and process all of them without having to do any extra work.

 np.mean(a.reshape(2, 2, 2, 3), axis=(1, 3))

Best way to take mean/sum of block matrix in numpy?

In [1952]: test=np.arange(81).reshape(9,9)
In [1953]: res=np.zeros((3,3))
In [1954]: for i in range(3):
...: for j in range(3):
...: res[i,j]=test[3*i:3*(i+1),3*j:3*(j+1)].mean()
In [1955]: res
Out[1955]:
array([[ 10., 13., 16.],
[ 37., 40., 43.],
[ 64., 67., 70.]])

With reshape and sum or mean on selected axes:

In [1956]: test.reshape(3,3,3,3).mean(axis=(1,3))
Out[1956]:
array([[ 10., 13., 16.],
[ 37., 40., 43.],
[ 64., 67., 70.]])

sum/mean allows us to specify 2 or more axes at a time, but it can also be done with repeated single axis applications.

test.reshape(3,3,3,3).mean(3).mean(1)

For the 3d array, these work

test.reshape( 2,3,3,3,3).mean((2,4))
test.reshape(-1,3,3,3,3).mean((2,4))

The -1 preserves the original 1st dimension (or in the case of a 2d test, it adds a size 1 dimension).

How to find a sum 3 elements in array?

You try to calculate sby using values from s. Dont you mean s(n)=A(n-2)+A(n-1)+A(n);? Also size returns more than one dimension on its own.

That being said, getting the 2 privous values n-2 and n-1 doenst work for n=1;2 (because you must have positive indices). You have to explain how the first two values should be handeled. I assume either 0 for elements not yet exisiting

k=size(A,2); %only the second dimension when A 1xn, or length(A) 
s=zeros(1,k); %get empty values instead of appending each value for better performance
s(1)=A(1);
s(2)=A(2)+A(1);
for n=3:k %start at 3
s(n)=A(n-2)+A(n-1)+A(n);
end

or sshoult be 2 values shorter than A.

k=size(A,2);
s=zeros(1,k-2);
for n=1:k-2
s(n)=A(n)+A(n+1)+A(n+2);
end

Sum array of numbers

The usual way of doing that would be this:

def sum(nums) nums.reduce(&:+) end

which is short for something like this:

def sum(nums)  nums.reduce(0) { |total, num| total + num } end

I see that Neil posted a similar solution while I was typing this, so I'll just note that reduce and inject are two names for the same method - Ruby has several aliases like this so that people used to different other languages can find what they're looking for. He also left off the &, which is optional when using a named method for reduce/inject, but not in other cases.

Explanation follows.

In Ruby you don't normally use explicit loops (for, while, etc.). Instead you call methods on the collection you're iterating over, and pass them a block of code to execute on each item. Ruby's syntax places the block after the arguments to the method, between either do...end or {...}, so it looks like traditional imperative flow control, but it works differently.

The basic iteration method is each:

[1,2,3].each do |i| puts i end

That calls the block do |i| puts i end three times, passing it 1, then passing it 2, and finally passing it 3. The |i| is a block parameter, which tells Ruby where to put the value(s) passed into the block each time.

But each just throws away the return value of the block calls (in this case, the three nils returned by puts). If you want to do something with those return values, you have to call a different method. For example, map returns an array of the return values:

[1,2,3].map do |i| puts i end
#=> [nil, nil, nil]

That's not very interesting here, but it becomes more useful if the block returns something:

[1,2,3].map do |i| 2*i end  
#=> [2,4,6]

If you want to combine the results into a single aggregate return value instead of getting back an array that's the same size as the input, that's when you reach for reduce. In addition to a block, it takes an extra argument, and the block itself is also called with an extra argument. The extra parameter corresponding to this argument is called the "accumulator"; the first time the block is called, it gets the argument originally passed to reduce, but from then on, it gets the return value of the previous call to the block, which is how each block call can pass information along to the next.

That makes reduce more general than map; in fact, you can build map out of reduce by passing in an empty array and having the block add to it:

[1,2,3].reduce([]) do |a,i| a + [2*i] end 
#=> [2,4,6]

But since map is already defined, you would normally just use it for that, and only use reduce to do things that are more, well, reductive:

[1,2,3].reduce(0) do |s, i| s + 2*i end  
#=> 12

...which is what we're doing in solving your problem.

Neil and I took a couple extra shortcuts. First, if a block does nothing but call a single method on its parameters and return the result, you can get an equivalent block by prefixing &: to the method name. That is, this:

some_array.reduce(x) do |a,b| a.some_method(b) end

can be rewritten more simply as this:

some_array.reduce(x, &:some_method)

and since a + b in Ruby is really just a more-familiar way of writing the method call a.+(b), that means that you can add up numbers by just passing in &:+:

[1,2,3].reduce(0, &:+)
#=> 6

Next, the initial accumulator value for reduce is optional; if you leave it out, then the first time the block is called, it gets the first two elements of the array. So you can leave off the 0:

[1,2,3].reduce(&:+)
#=> 6

Finally, you normally need the & any time you are passing in a block that is not a literal chunk of code. You can turn blocks into Proc objects and store them in variables and in general treat them like any other value, including passing them as regular arguments to method calls. So when you want to use one as the block on a method call instead, you indicate that with the &.

Some methods, including reduce, will also accept a bare Symbol (like :+) and create the Proc/block for you; and Neil took advantage of that fact. But other iterator methods, such as map, don't work that way:

irb(main):001:0> [-1,2,-3].map(:abs)
ArgumentError: wrong number of arguments (1 for 0)
from (irb):1:in `map'
from (irb):1
from /usr/bin/irb:12:in `<main>'

So I just always use the &.

irb(main):002:0> [-1,2,-3].map(&:abs)
#=> [1, 2, 3]

There are lots of good online tutorials for Ruby. For more general information about map/reduce and related concepts, and how to apply them to problem-solving, you should search for introductions to "functional programming", which is called that because it treats "functions" (that is, blocks of executable code, which in Ruby are realized as Proc objects) as values just like numbers and strings, which can be passed around, assigned to variables, etc.



Related Topics



Leave a reply



Submit