2

In Python, let's say I have a 1366x768 numpy array. And I want to delete each second row from it (0th row remains, 1st removed, 2nd remains, 3rd removed.. and so on), and replace the empty space with a duplicate from the row which was before it (the undeleted row) at the same time.

Is it possible in numpy?

3 Answers 3

3

One approach -

a[::2].repeat(2,axis=0)

To make the changes in the array, assign it back.

Sample run -

In [105]: a
Out[105]: 
array([[2, 5, 1, 1],
       [2, 0, 2, 5],
       [1, 1, 5, 7],
       [0, 7, 1, 8],
       [8, 5, 2, 3],
       [2, 1, 0, 6],
       [5, 6, 1, 6],
       [7, 1, 4, 7],
       [3, 8, 1, 4],
       [5, 8, 8, 8]])

In [106]: a[::2].repeat(2,axis=0)
Out[106]: 
array([[2, 5, 1, 1],
       [2, 5, 1, 1],
       [1, 1, 5, 7],
       [1, 1, 5, 7],
       [8, 5, 2, 3],
       [8, 5, 2, 3],
       [5, 6, 1, 6],
       [5, 6, 1, 6],
       [3, 8, 1, 4],
       [3, 8, 1, 4]])

If we care about performance, here's another approach using NumPy strides -

def strided_app(a):
    m0,n0 = a.strides
    m,n = a.shape
    strided = np.lib.stride_tricks.as_strided
    return strided(a,shape=(m//2,2,n),strides=(2*m0,0,n0)).reshape(-1,n)

Sample run -

In [154]: a
Out[154]: 
array([[4, 8, 7, 7],
       [5, 5, 1, 7],
       [1, 8, 1, 3],
       [6, 6, 5, 6],
       [0, 2, 6, 3],
       [6, 6, 8, 7],
       [7, 6, 8, 1],
       [7, 8, 8, 2],
       [4, 0, 2, 8],
       [5, 8, 1, 4]])

In [155]: strided_app(a)
Out[155]: 
array([[4, 8, 7, 7],
       [4, 8, 7, 7],
       [1, 8, 1, 3],
       [1, 8, 1, 3],
       [0, 2, 6, 3],
       [0, 2, 6, 3],
       [7, 6, 8, 1],
       [7, 6, 8, 1],
       [4, 0, 2, 8],
       [4, 0, 2, 8]])

Timings -

In [156]: arr = np.arange(1000000).reshape(1000, 1000)

# Proposed soln-1
In [157]: %timeit arr[::2].repeat(2,axis=0)
1000 loops, best of 3: 1.26 ms per loop

# @Psidom 's soln
In [158]: %timeit arr[1::2] = arr[::2]
1000 loops, best of 3: 928 µs per loop

In [159]: arr = np.arange(1000000).reshape(1000, 1000)

# Proposed soln-2
In [160]: %timeit strided_app(arr)
1000 loops, best of 3: 830 µs per loop
Sign up to request clarification or add additional context in comments.

Comments

2

Looks like you have an even number of rows, in which case, you can use assignment (assign the odd rows values to corresponding even rows):

arr = np.array([[1,4],[3,1],[2,3],[2,2]])
arr[1::2] = arr[::2]
arr
#array([[1, 4],
#       [1, 4],
#       [2, 3],
#       [2, 3]])

This avoids copying the entire array, but doesn't work if the array has odd number of rows.

Timing: Here is a comparison of the timing, the assignment does seem faster.

arr = np.arange(1000000).reshape(1000, 1000)

%timeit arr[::2].repeat(2,axis=0)
1000 loops, best of 3: 913 µs per loop

%timeit arr[1::2] = arr[::2]
1000 loops, best of 3: 655 µs per loop

4 Comments

Looks pretty efficient for in-place assignment.
@Divakar It could be. Kind of awkward only work for even number of rows array though. I'll add some timing.
Added another approach with strides. It's just crazy that strides is beating a simple assignment step.
@Divakar That's quite impressive. strides is still a quite new concept to me. -
0

This works for both even and an odd number of rows.

for i in range(1,len(a),2):
    a[i] = a[i-1]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.