61

Is there a numpy method which is equivalent to the builtin pop for python lists?

Popping obviously doesn't work on numpy arrays, and I want to avoid a list conversion.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93
Anton Alice
  • 723
  • 1
  • 6
  • 10
  • 1
    pop doesn't exist in numpy and by design it is not recommended to emulate it. You would better approach the algorithm you need to write without using a pop pattern – Zeugma Oct 09 '16 at 15:52

10 Answers10

34

There is no pop method for NumPy arrays, but you could just use basic slicing (which would be efficient since it returns a view, not a copy):

In [104]: y = np.arange(5); y
Out[105]: array([0, 1, 2, 3, 4])

In [106]: last, y = y[-1], y[:-1]

In [107]: last, y
Out[107]: (4, array([0, 1, 2, 3]))

If there were a pop method it would return the last value in y and modify y.

Above,

last, y = y[-1], y[:-1]

assigns the last value to the variable last and modifies y.

unutbu
  • 842,883
  • 184
  • 1,785
  • 1,677
23

Here is one example using numpy.delete():

import numpy as np
arr = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
print(arr)
#  array([[ 1,  2,  3,  4],
#         [ 5,  6,  7,  8],
#         [ 9, 10, 11, 12]])
arr = np.delete(arr, 1, 0)
print(arr)
# array([[ 1,  2,  3,  4],
#        [ 9, 10, 11, 12]])
GMSL
  • 355
  • 2
  • 11
mozlingyu
  • 433
  • 3
  • 4
8

Pop doesn't exist for NumPy arrays, but you can use NumPy indexing in combination with array restructuring, for example hstack/vstack or numpy.delete(), to emulate popping.

Here are some example functions I can think of (which apparently don't work when the index is -1, but you can fix this with a simple conditional):

def poprow(my_array,pr):
    """ row popping in numpy arrays
    Input: my_array - NumPy array, pr: row index to pop out
    Output: [new_array,popped_row] """
    i = pr
    pop = my_array[i]
    new_array = np.vstack((my_array[:i],my_array[i+1:]))
    return [new_array,pop]

def popcol(my_array,pc):
    """ column popping in numpy arrays
    Input: my_array: NumPy array, pc: column index to pop out
    Output: [new_array,popped_col] """
    i = pc
    pop = my_array[:,i]
    new_array = np.hstack((my_array[:,:i],my_array[:,i+1:]))
    return [new_array,pop]

This returns the array without the popped row/column, as well as the popped row/column separately:

>>> A = np.array([[1,2,3],[4,5,6]])
>>> [A,poparow] = poprow(A,0)
>>> poparow
array([1, 2, 3])

>>> A = np.array([[1,2,3],[4,5,6]])
>>> [A,popacol] = popcol(A,2)
>>> popacol
array([3, 6])
dbouz
  • 779
  • 9
  • 14
6

There isn't any pop() method for numpy arrays unlike List, Here're some alternatives you can try out-

  • Using Basic Slicing
>>> x = np.array([1,2,3,4,5])
>>> x = x[:-1]; x
>>> [1,2,3,4]
  • Or, By Using delete()

Syntax - np.delete(arr, obj, axis=None)

arr: Input array
obj: Row or column number to delete
axis: Axis to delete

>>> x = np.array([1,2,3,4,5])
>>> x = x = np.delete(x, len(x)-1, 0)
>>> [1,2,3,4]
Rahul Bordoloi
  • 145
  • 3
  • 9
3

The important thing is that it takes one from the original array and deletes it. If you don't m ind the superficial implementation of a single method to complete the process, the following code will do what you want.

import numpy as np

a = np.arange(0, 3)
i = 0
selected, others = a[i], np.delete(a, i)

print(selected)
print(others)

# result:
# 0
# [1 2]
miorgash
  • 31
  • 2
2

The most 'elegant' solution for retrieving and removing a random item in Numpy is this:

import numpy as np
import random

arr = np.array([1, 3, 5, 2, 8, 7])
element = random.choice(arr)
elementIndex = np.where(arr == element)[0][0]
arr = np.delete(arr, elementIndex)

For curious coders:

The np.where() method returns two lists. The first returns the row indexes of the matching elements and the second the column indexes. This is useful when searching for elements in a 2d array. In our case, the first element of the first returned list is interesting.

Alex F.
  • 96
  • 4
0

To add, If you want to implement pop for a row or column from a numpy 2D array you could do like:

col = arr[:, -1] # gets the last column
np.delete(arr, -1, 1) # deletes the last column

and for row:

row = arr[-1, :] # gets the last row
np.delete(arr, -1, 0) # deletes the last row
0

unutbu had a simple answer for this, but pop() can also take an index as a parameter. This is how you replicate it with numpy:

pop_index = 4
pop = y[pop_index]
y = np.concatenate([y[:pop_index],y[pop_index+1:]])
huynv
  • 49
  • 5
-1

OK, since I didn't see a good answer that RETURNS the 1st element and REMOVES it from the original array, I wrote a simple (if kludgy) function utilizing global for a 1d array (modification required for multidims):

tmp_array_for_popfunc = 1d_array

def array_pop():
    global tmp_array_for_popfunc
    
    r = tmp_array_for_popfunc[0]
    tmp_array_for_popfunc = np.delete(tmp_array_for_popfunc, 0)
    return r

check it by using-

print(len(tmp_array_for_popfunc)) # confirm initial size of tmp_array_for_popfunc
print(array_pop()) #prints return value at tmp_array_for_popfunc[0]
print(len(tmp_array_for_popfunc)) # now size is 1 smaller
Bernd Wechner
  • 1,854
  • 1
  • 15
  • 32
Saqster
  • 119
  • 1
  • 1
  • 8
  • I'm curious, why use global and not pass `1d_array` as an argument? – Bernd Wechner Aug 09 '22 at 23:44
  • DISCLAIMER: I'm no expert so I could be wrong. If we didn't operate on the original array (1d_array) as global, any changes made to the passed array in the function would not "Stick" due to scope issues. Non global would require an extra step to return the modified array and then overwrite the original array. Thereby not having a true pop function. Try it and you can see. I recall, in C we would not need to use a global and could pass a pointer to the original array to a function and then all modification to the the original array would "stick", I'm not aware of how to do that in Python. – Saqster Aug 25 '22 at 04:02
  • The proper way to answer is to say: There are NO POPs and you should implement one yourself first. – Ash Jan 20 '23 at 20:55
-1

I made a function as follow, doing almost the same. This function has 2 arguments: np_array and index, and return the value of the given index of the array.

def np_pop(np_array, index=-1):
    '''
    Pop the "index" from np_array and return the value. 
    Default value for index is the last element.
    '''
    # add this to make sure 'numpy' is imported 
    import numpy as np
    # read the value of the given array at the given index
    value = np_array[index]
    # remove value from array
    np.delete(np_array, index, 0)
    # return the value
    return value

Remember you can add a condition to make sure the given index is exist in the array and return -1 if anything goes wrong.

Now you can use it like this:

import numpy as np
i = 2 # let's assume we want to pop index number 2
y = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9]) # assume 'y' is our numpy array 
poped_val = np_pop(y, i) # value of the piped index
ViKi
  • 1
  • 1