Qubix
Qubix

Reputation: 4353

Adding a new row in a matrix, every other row, whose elements are averages of the elements above and below it

I have a matrix, say:

A = [1, 2, 3]
    [4, 5, 6]
    [7, 8, 9]

and I want to construct another matrix, having two extra rows as such

B = [1,    2,    3]
    [2.5, 3.5, 4.5]
    [4,     5,   6]
    [5.5, 6.5, 7.5]
    [7,     8,   9]

where every element on the second and fourth row is the average of the elements above and below it.

I want to do this, in python, numpy, for an n x m matrix.

EDIT: The generalization to this would be to insert the means of two neighboring rows every n rows. For example

     A = [ 1,  2,  3]
         [ 4,  5,  6]
         [ 7,  8,  9]
         [10, 11, 12]
         [13, 14, 15]
         [16, 17, 18]
         [19, 20, 21]

and , for n = 3 , B would become

     B = [ 1,  2,  3]
         [ 4,  5,  6]
         [ 7,  8,  9]
         [8.5, 9.5, 10.5]
         [10, 11, 12]
         [13, 14, 15]
         [16, 17, 18]
         [17.5, 18.5, 19.5]
         [19, 20, 21]

and so on. The AVERAGE layers are still the average of the one above and the one below them. I am looking for a function that would give this for any n.

Upvotes: 2

Views: 129

Answers (2)

Divakar
Divakar

Reputation: 221614

Here's an approach making use of slicing -

newvals = (A[1:] + A[:-1])/2.0
out = np.empty((A.shape[0]+newvals.shape[0],A.shape[1]))
out[::2] = A
out[1::2] = newvals

Here's another one with np.insert for a generic case -

np.insert(A.astype(float),range(1,A.shape[0]),newvals,axis=0)

Generalizing to handle every possible n -

def insert_row_averages(A, n=1):
    slice2 = A[n::n]
    v = (A[n-1::n][:slice2.shape[0]] + slice2)/2.0
    return np.insert(A.astype(float),n*np.arange(1,v.shape[0]+1),v,axis=0)

Sample runs -

In [195]: A0
Out[195]: 
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])

In [196]: insert_row_averages(A0, n=1)
Out[196]: 
array([[ 1. ,  2. ,  3. ],
       [ 2.5,  3.5,  4.5],
       [ 4. ,  5. ,  6. ],
       [ 5.5,  6.5,  7.5],
       [ 7. ,  8. ,  9. ]])

In [197]: A
Out[197]: 
array([[ 1,  2,  3],
       [ 4,  5,  6],
       [ 7,  8,  9],
       [10, 11, 12],
       [13, 14, 15],
       [16, 17, 18],
       [19, 20, 21]])

In [198]: insert_row_averages(A, n=3)
Out[198]: 
array([[  1. ,   2. ,   3. ],
       [  4. ,   5. ,   6. ],
       [  7. ,   8. ,   9. ],
       [  8.5,   9.5,  10.5],
       [ 10. ,  11. ,  12. ],
       [ 13. ,  14. ,  15. ],
       [ 16. ,  17. ,  18. ],
       [ 17.5,  18.5,  19.5],
       [ 19. ,  20. ,  21. ]])

Upvotes: 4

akuiper
akuiper

Reputation: 215047

One option would be to calculate the averages and then insert it back to A:

np.insert(A.astype(float), [1,2], (A[1:] + A[:-1])/2, axis=0)

#array([[ 1. ,  2. ,  3. ],
#       [ 2.5,  3.5,  4.5],
#       [ 4. ,  5. ,  6. ],
#       [ 5.5,  6.5,  7.5],
#       [ 7. ,  8. ,  9. ]])

Upvotes: 1

Related Questions