I have a problem that can be fully vectorised, but I don't have enough space, so I am trying for a half and half solution, using numpy's apply_along_axis().
(NOTE: This is a toy example that illustrates the nub of the problem. In other words, I am not looking for a numpy or scipy function that does what the function here is doing - it is not the real function, just one that is simple to illustrate with.)
What I would like to do is figure out a way to access the index of the axis being passed at each iteration.
Say we took a 4 x 4 matrix:
M = np.array(([0,0,1,1], [1,1,0,1], [1,0,1,0], [0,0,1,1]))
M
array([[0, 0, 1, 1],
[1, 1, 0, 1],
[1, 0, 1, 0],
[0, 0, 1, 1]])
And wanted to compute the pairwise bitwise logical and of each column against every other column, but to save (a lot of) time, we only compute for columns i,j where index of j > i (so that we end up with a triangular matrix).
In pandas I can do this quite easily with apply(), but it is too slow for my purposes.
I know there are pairwise functions in scikit-learn, but please assume these do not suit my purposes (my function is more complicated than this toy one)
If I were to use numpy's apply_long_axis(), I can only work out how to compare all i,j and j,i, not the smaller problem as described before.
This is my solution:
def intersections_np(col, M):
col = col[:,np.newaxis]
intersection = (M & col).sum(0)
return(intersection)
result_np = np.apply_along_axis(intersections_np, arr = M, axis = 0, M = M)
result_np
array([[2, 1, 1, 1],
[1, 1, 0, 1],
[1, 0, 3, 2],
[1, 1, 2, 3]], dtype=int32)
But what I would really like to do is something like:
def intersections_np(col, M):
col = col[:,np.newaxis]
start_index = <index_of_current_column> + 1
other_cols = M[:,start_index:]
intersection = (other_cols & col).sum(0)
<possible padding of the array with nans here>
return(intersection)
result_np = np.apply_along_axis(intersections_np, arr = M, axis = 0, M = M)
and return:
result_np
array([[nan, nan, nan, nan],
[1, nan, nan, nan],
[1, 0, nan, nan],
[1, 1, 2, nan]], dtype=int32)
Does any one know if something like this can be done?
Thanks