Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Randomly remove 'x' elements from a list

I'd like to randomly remove a fraction of elements from a list without changing the order of the list.

Say I had some data and I wanted to remove 1/4 of them:

data = [1,2,3,4,5,6,7,8,9,10]
n    = len(data) / 4

I'm thinking I need a loop to run through the data and delete a random element 'n' times? So something like:

for i in xrange(n):
    random = np.randint(1,len(data))
    del data[random]

My question is, is this the most 'pythonic' way of doing this? My list will be ~5000 elements long and I want to do this multiple times with different values of 'n'.

Thanks!

like image 825
rh1990 Avatar asked Jul 03 '17 11:07

rh1990


People also ask

How do I remove a specific data from a list?

To remove an element from a list using the remove() method, specify the value of that element and pass it as an argument to the method. remove() will search the list to find it and remove it.

How do you pop a random item from a list in Python?

The simplest way to use Python to select a single random element from a list in Python is to use the random. choice() function. The function takes a single parameter – a sequence. In this case, our sequence will be a list, though we could also use a tuple.

How do you remove a random element from a set in Python?

To remove an item in a set, use the remove() , or the discard() method.


2 Answers

Sequential deleting is a bad idea since deletion in a list is O(n). Instead do something like this:

def delete_rand_items(items,n):
    to_delete = set(random.sample(range(len(items)),n))
    return [x for i,x in enumerate(items) if not i in to_delete]
like image 176
John Coleman Avatar answered Oct 01 '22 19:10

John Coleman


You can use random.sample like this:

import random

a = [1,2,3,4,5,6,7,8,9,10]

no_elements_to_delete = len(a) // 4
no_elements_to_keep = len(a) - no_elements_to_delete
b = set(random.sample(a, no_elements_to_keep))  # the `if i in b` on the next line would benefit from b being a set for large lists
b = [i for i in a if i in b]  # you need this to restore the order
print(len(a))  # 10
print(b)       # [1, 2, 3, 4, 5, 8, 9, 10]
print(len(b))  # 8

Two notes on the above.

  1. You are not modifying the original list in place but you could.
  2. You are not actually deleting elements but rather keeping elements but it is the same thing (you just have to adjust the ratios)
  3. The drawback is the list-comprehension that restores the order of the elements

As @koalo says in the comments the above will not work properly if the elements in the original list are not unique. I could easily fix that but then my answer would be identical to the one posted by@JohnColeman. So if that might be the case just use his instead.

like image 43
Ma0 Avatar answered Oct 01 '22 20:10

Ma0