Given two arrays, say
arr = array([10, 24, 24, 24, 1, 21, 1, 21, 0, 0], dtype=int32)
rep = array([3, 2, 2, 0, 0, 0, 0, 0, 0, 0], dtype=int32)
np.repeat(arr, rep) returns
array([10, 10, 10, 24, 24, 24, 24], dtype=int32)
Is there any way to replicate this functionality for a set of 2D arrays?
That is given
arr = array([[10, 24, 24, 24, 1, 21, 1, 21, 0, 0],[10, 24, 24, 1, 21, 1, 21, 32, 0, 0]], dtype=int32)
rep = array([[3, 2, 2, 0, 0, 0, 0, 0, 0, 0],[2, 2, 2, 0, 0, 0, 0, 0, 0, 0]], dtype=int32)
is it possible to create a function which vectorizes?
PS: The number of repeats in each row need not be the same. I'm padding each result row to ensure that they are of same size.
def repeat2d(arr, rep):# Find the max length of repetitions in all the rows. max_len = rep.sum(axis=-1).max() # Create a common array to hold all results. Since each repeated array will have # different sizes, some of them are padded with zero.ret_val = np.empty((arr.shape[0], maxlen)) for i in range(arr.shape[0]):# Repeated array will not have same num of cols as ret_val.temp = np.repeat(arr[i], rep[i])ret_val[i,:temp.size] = tempreturn ret_val
I do know about np.vectorize and I know that it does not give any performance benefits over the normal version.
So you have a different repeat array for each row? But the total number of repeats per row is the same?
Just do the repeat
on the flattened arrays, and reshape back to the correct number of rows.
In [529]: np.repeat(arr,rep.flat)
Out[529]: array([10, 10, 10, 24, 24, 24, 24, 10, 10, 24, 24, 24, 24, 1])
In [530]: np.repeat(arr,rep.flat).reshape(2,-1)
Out[530]:
array([[10, 10, 10, 24, 24, 24, 24],[10, 10, 24, 24, 24, 24, 1]])
If the repetitions per row vary, we have the problem of padding variable length rows. That's come up in other SO questions. I don't recall all the details, but I think the solution is along this line:
Change rep
so the numbers differ:
In [547]: rep
Out[547]:
array([[3, 2, 2, 0, 0, 0, 0, 0, 0, 0],[2, 2, 2, 1, 0, 2, 0, 0, 0, 0]])
In [548]: lens=rep.sum(axis=1)
In [549]: lens
Out[549]: array([7, 9])
In [550]: m=np.max(lens)
In [551]: m
Out[551]: 9
create the target:
In [552]: res = np.zeros((arr.shape[0],m),arr.dtype)
create an indexing array - details need to be worked out:
In [553]: idx=np.r_[0:7,m:m+9]
In [554]: idx
Out[554]: array([ 0, 1, 2, 3, 4, 5, 6, 9, 10, 11, 12, 13, 14, 15, 16, 17])
flat indexed assignment:
In [555]: res.flat[idx]=np.repeat(arr,rep.flat)
In [556]: res
Out[556]:
array([[10, 10, 10, 24, 24, 24, 24, 0, 0],[10, 10, 24, 24, 24, 24, 1, 1, 1]])