Reputation: 892
Trying to build a numpy matrix without double for loops
if i have a matrix:
x = [val, val, val]
[val, val, val]
[val, val, val]
and I want to subtract each row's items with the other two rows while simultaneously extrapolating to a larger matrix with final result. Each row substraction (in this example) is 3 elements. (I'm doing it with larger matrices though)
new = [row 1 - 2, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[row 1 - 3, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, row 2 - 1, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, row 2 - 3, 0.0, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0 row 3 - 1]
[0.0, 0.0, 0.0, 0.0, 0.0, 0.0 row 3 - 2]
And then similar but with the columns instead except the items are filled in horizontally, if that makes sense (each item is a single value vs above)
new = [col 1 - 2, 0.0, 0.0, col 1 - 2, 0.0, 0.0, col 1 - 2, 0.0, 0.0]
[col 1 - 3, 0.0, 0.0, col 1 - 3, 0.0, 0.0, col 1 - 3, 0.0, 0.0]
[0.0, col 2 - 1, 0.0, 0.0, col 2 - 1, 0.0, 0.0, col 2 - 1, 0.0]
[0.0, col 2 - 3, 0.0, 0.0, col 2 - 3, 0.0, 0.0, col 2 - 3, 0.0]
[0.0, 0.0, col 3 - 1, 0.0, 0.0, col 3 - 1, 0.0, 0.0, col 3 - 1]
[0.0, 0.0, col 3 - 2, 0.0, 0.0, col 3 - 2, 0.0, 0.0, col 3 - 2]
If someone has the numpy magic to figure this, I'll lose it ha.
Edit: better example with small matrix:
x = [[.5, 0.],
[.1, 1.2]]
turns into
new = [[ 0.4, -1.2, 0., 0. ],
[ 0., 0., -0.4, 1.2]]
and for column version
y = [[.2, .9],
[.6, .1]]
turns into
new = [[-0.7, 0., 0.5, 0. ],
[ 0., 0.7, 0., -0.5]]
Upvotes: 2
Views: 205
Reputation: 53029
Here is some indexing madness which I believe does what you are asking for:
>>> def magic(data):
... n, m = data.shape
... assert n==m
... rows = np.zeros((n, n-1, n, n), data.dtype)
... cols = np.zeros((n, n-1, n, n), data.dtype)
... idx = np.argsort(np.identity(n), kind='mergesort', axis=1)
... self = idx[:, -1] # should be just 0, 1, 2, 3, ...
... other = idx[:, :-1]
... rows[self, :, self, :] = data[:, None, :] - data[other[..., None], self]
... cols[self, ..., self] = data.T[:, None, :] - data.T[other[..., None], self]
... return rows.reshape(-1, n*n), cols.reshape(-1, n*n)
...
>>> magic(np.array([[.5,0], [.1,1.2]]))
(array([[ 0.4, -1.2, 0. , 0. ],
[ 0. , 0. , -0.4, 1.2]]), array([[ 0.5, 0. , -1.1, 0. ],
[ 0. , -0.5, 0. , 1.1]]))
>>> magic(np.array([[.2,.9], [.6,.1]]))
(array([[-0.4, 0.8, 0. , 0. ],
[ 0. , 0. , 0.4, -0.8]]), array([[-0.7, 0. , 0.5, 0. ],
[ 0. , 0.7, 0. , -0.5]]))
Upvotes: 3