Rtrader
Rtrader

Reputation: 947

How to divide one columns value by a previous rows column(not the same column) and add the result as a new dimension to a numpy array?

What I want to do is take a numpy array like this:

[[1, 2,  4, 7,  9, 15,  0],
 [3, 4,  3, 5, 10,  2, -2],
 [5, 6, 56, 7, 20,  1,  2]]

I want to take each rows last column and divide that by the previous row's 4th column and take the result and add it to the array as a new dimension the output I want should look like this

[[1, 2,  4, 7,  9, 15,  0,  0],
 [3, 4,  3, 5, 10,  2, -2, -.2857],
 [5, 6, 56, 7, 20,  1,  2, .4]]

Can this be done without a for loop? (Ok I guess it's not efficient to do this without a for loop) But I'm still not sure how to do it with one either

Upvotes: 0

Views: 1887

Answers (4)

fraxel
fraxel

Reputation: 35269

import numpy as np
myarray = np.array([[1,2,4,7,9,15,0.0], [3, 4,3,5,10,2,-2], [5,6,56,7,20,1,2]])
#the division:
column_divs = myarray[:,-1][1:] / myarray[:,3][:-1]
#adds a 'placeholder' zero value, as the first element:
column_divs = np.hstack(([0], column_divs))
#adds the required column to the end of the array:
print np.hstack((myarray, column_divs.reshape(-1,1)))
#output:
[[  1.      2.       4.       7.       9.      15.      0.       0.        ]
 [  3.      4.       3.       5.      10.       2.     -2.      -0.28571429]
 [  5.      6.      56.       7.      20.       1.      2.      0.4        ]]

Upvotes: 2

ecatmur
ecatmur

Reputation: 157374

You'll want to use np.concatenate:

np.concatenate((a, np.concatenate(([[0]], a[1:, [-1]] / a[:-1, [3]].astype(float)))), axis=1)

The astype(float) is required for Python 2.x if your array has int dtype.

This can be also written with hstack and vstack:

np.hstack((a, np.vstack(([[0]], a[1:, [-1]] / a[:-1, [3]].astype(float)))))

Instead of slicing the rows, it may be OK to use roll:

np.hstack((a, np.vstack((a[:, [-1]] / np.roll(a[:, [3]], 1).astype(float)))))

Upvotes: 1

Ben Burns
Ben Burns

Reputation: 15216

Apologies in advance for the non-answer, but unless you're prioritizing algorithmic purity over performance, you definitely want to do this with a for loop or similar construct.

There's probably a way to accomplish this purely with matrix operations (multiply the original by a custom kernel and concatenate the result as a new column on the original matrix) but it won't be as efficient. Consider that Strassen's algorithm (an example of efficient multiplication of two square matrices) is O(n^log7), or ~O(n^2.807) where n is the size of the matrices being multiplied in terms of number of elements. A for loop would be O(m), where m is the number of rows in the matrix in question.

Upvotes: 0

Ashwini Chaudhary
Ashwini Chaudhary

Reputation: 250971

import numpy as np
lis=[[1, 2,  4, 7,  9, 15,  0],
 [3, 4,  3, 5, 10,  2, -2],
 [5, 6, 56, 7, 20,  1,  2]]
new_lis=[lis[i][:]+[lis[i][-1]/lis[i][3]] for i in range(len(lis))]
nparray=np.matrix(new_lis)

Upvotes: 1

Related Questions