Làm thế nào để loại bỏ các yếu tố cụ thể trong một mảng numpy


212

Làm thế nào tôi có thể loại bỏ một số yếu tố cụ thể từ một mảng numpy? Nói tôi có

import numpy as np

a = np.array([1,2,3,4,5,6,7,8,9])

Sau đó tôi muốn loại bỏ 3,4,7khỏi a. Tất cả những gì tôi biết là chỉ số của các giá trị ( index=[2,3,6]).

Câu trả lời:


284

Sử dụng numpy.delete () - trả về một mảng mới với các mảng con dọc theo một trục bị xóa

numpy.delete(a, index)

Đối với câu hỏi cụ thể của bạn:

import numpy as np

a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
index = [2, 3, 6]

new_a = np.delete(a, index)

print(new_a) #Prints `[1, 2, 5, 6, 8, 9]`

Lưu ý rằng numpy.delete()trả về một mảng mới vì các vô hướng mảng là bất biến, tương tự như các chuỗi trong Python, vì vậy mỗi lần thay đổi được thực hiện cho nó, một đối tượng mới được tạo. Tức là, để trích dẫn các delete() tài liệu :

"Một bản sao của mảng với các thành phần được chỉ định bởi obj đã bị xóa. Lưu ý rằng việc xóa không xảy ra tại chỗ ..."

Nếu mã tôi đăng có đầu ra, đó là kết quả của việc chạy mã.


1
@IngviGautsson Khi bạn thực hiện chỉnh sửa của mình, bạn cũng đã thay đổi các giá trị chính xác cho các phần tử từ 2, 3, 6 thành 3, 4, 7, nếu bạn chạy mã bây giờ, bạn không nhận được đầu ra chính xác như ban đầu. "Tôi quay lại bản chỉnh sửa
Levon

1
AttributionError: 'list' object không có thuộc tính 'xóa'
munmunbb

3
@IngviGautsson Không, nhận xét của bạn là sai lệch. Điều này hoạt động như mong đợi. Tuy nhiên, tài liệu của numpy.delete () không lưu ý rằng "thường thì nên sử dụng mặt nạ boolean"; một ví dụ về điều đó cũng được đưa ra.
Biggsy

1
@Levon bạn có thể thêm ví dụ cho 2D không?
MattS

7
@IngviGautsson Bạn sai rồi. Nó có các chỉ số của các mục để xóa, không phải các mục chính.
Le Frite 17/07/19

64

Có một chức năng tích hợp gọn gàng để giúp với điều đó.

import numpy as np
>>> a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])
>>> b = np.array([3,4,7])
>>> c = np.setdiff1d(a,b)
>>> c
array([1, 2, 5, 6, 8, 9])

7
Tốt để biết. Tôi đã nghĩ rằng np.delete sẽ chậm hơn nhưng than ôi, thời gian cho 1000 số nguyên nói rằng xóa là x2 nhanh hơn.
wbg

1
Điều này thật tuyệt vì nó hoạt động dựa trên các giá trị của mảng thay vì phải cung cấp chỉ mục / chỉ mục bạn muốn xóa. Ví dụ:np.setdiff1d(np.array(['one','two']),np.array(['two', 'three']))
MD004

Điều này cũng sắp xếp đầu ra, có thể không phải là những gì muốn. Nếu không thì rất đẹp.
rayzinnz

Câu hỏi cho biết "Tất cả những gì tôi biết là chỉ số của các giá trị". Vì vậy, đó là về việc xóa các mục theo chỉ mục của chúng , không xóa bằng các giá trị của chúng
Sherzod

35

Một mảng Numpy là bất biến , có nghĩa là về mặt kỹ thuật bạn không thể xóa một mục khỏi nó. Tuy nhiên, bạn có thể xây dựng một mảng mới mà không cần các giá trị bạn không muốn, như thế này:

b = np.delete(a, [2,3,6])

1
+1 để đề cập đến "bất biến". Điều tốt cần nhớ là, mảng numpy không tốt cho việc thay đổi kích thước nhanh chóng (nối thêm / xóa các yếu tố)
eumiro

38
về mặt kỹ thuật, mảng numpy là đột biến. Ví dụ: cái này: a[0]=1sửa đổi atại chỗ. Nhưng chúng không thể thay đổi kích thước.
btel

3
Định nghĩa nói nó bất biến, nhưng nếu bằng cách gán giá trị mới, nó cho phép bạn sửa đổi, sau đó có bất biến không?
JSR

16

Để xóa theo giá trị:

modified_array = np.delete(original_array, np.where(original_array == value_to_delete))

Câu hỏi là về việc xóa các mục theo chỉ mục , không xóa các mục có giá trị cụ thể
Sherzod

5

Không phải là một người khó chịu, tôi đã chụp:

>>> import numpy as np
>>> import itertools
>>> 
>>> a = np.array([1,2,3,4,5,6,7,8,9])
>>> index=[2,3,6]
>>> a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))
>>> a
array([1, 2, 5, 6, 8, 9])

Theo thử nghiệm của tôi, điều này vượt trội hơn numpy.delete(). Tôi không biết tại sao lại như vậy, có thể là do kích thước nhỏ của mảng ban đầu?

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
100000 loops, best of 3: 12.9 usec per loop

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "np.delete(a, index)"
10000 loops, best of 3: 108 usec per loop

Đó là một sự khác biệt khá đáng kể (theo hướng ngược lại với những gì tôi đang mong đợi), có ai biết tại sao lại như vậy không?

Thậm chí kỳ lạ hơn, việc vượt qua numpy.delete()một danh sách thực hiện tồi tệ hơn là lặp qua danh sách và đưa ra chỉ số duy nhất.

python -m timeit -s "import numpy as np" -s "a = np.array([1,2,3,4,5,6,7,8,9])" -s "index=[2,3,6]" "for i in index:" "    np.delete(a, i)"
10000 loops, best of 3: 33.8 usec per loop

Chỉnh sửa: Nó dường như là để làm với kích thước của mảng. Với mảng lớn, numpy.delete()nhanh hơn đáng kể.

python -m timeit -s "import numpy as np" -s "import itertools" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "a = np.array(list(itertools.compress(a, [i not in index for i in range(len(a))])))"
10 loops, best of 3: 200 msec per loop

python -m timeit -s "import numpy as np" -s "a = np.array(list(range(10000)))" -s "index=[i for i in range(10000) if i % 2 == 0]" "np.delete(a, index)"
1000 loops, best of 3: 1.68 msec per loop

Rõ ràng, điều này hoàn toàn không liên quan, vì bạn nên luôn luôn đi cho rõ ràng và tránh phát minh lại bánh xe, nhưng tôi thấy nó hơi thú vị, vì vậy tôi nghĩ tôi sẽ để nó ở đây.


2
Hãy cẩn thận với những gì bạn thực sự so sánh! Bạn có a = delte_stuff(a)trong lần lặp đầu tiên của mình, làm cho anhỏ hơn với mỗi lần lặp. Khi bạn sử dụng hàm inbuild, bạn không lưu trữ giá trị trở lại a, giữ cho kích thước ban đầu! Bên cạnh đó, bạn có thể tăng tốc chức năng của mình một cách quyết liệt, khi bạn tạo một tập hợp indexvà kiểm tra xem, có hay không xóa một mục. Sửa cả hai thứ, tôi nhận được 10k vật phẩm: 6,22 ms mỗi vòng lặp với chức năng của bạn, 4,48 msec numpy.delete, gần như là những gì bạn mong đợi.
Michael

2
Hai gợi ý nữa: Thay vì np.array(list(range(x)))sử dụng np.arange(x)và để tạo chỉ mục, bạn có thể sử dụng np.s_[::2].
Michael

1

Nếu bạn không biết chỉ mục, bạn không thể sử dụng logical_and

x = 10*np.random.randn(1,100)
low = 5
high = 27
x[0,np.logical_and(x[0,:]>low,x[0,:]<high)]

1

Sử dụng np.deletelà cách nhanh nhất để làm điều đó, nếu chúng ta biết các chỉ số của các yếu tố mà chúng ta muốn loại bỏ. Tuy nhiên, để hoàn thiện, hãy để tôi thêm một cách khác để "loại bỏ" các phần tử mảng bằng cách sử dụng mặt nạ boolean được tạo với sự trợ giúp của np.isin. Phương pháp này cho phép chúng tôi loại bỏ các yếu tố bằng cách chỉ định chúng trực tiếp hoặc bằng chỉ số của chúng:

import numpy as np
a = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9])

Xóa bởi các chỉ số :

indices_to_remove = [2, 3, 6]
a = a[~np.isin(np.arange(a.size), indices_to_remove)]

Xóa bởi các thành phần (đừng quên tạo lại bản gốc avì nó đã được viết lại ở dòng trước):

elements_to_remove = a[indices_to_remove]  # [3, 4, 7]
a = a[~np.isin(a, elements_to_remove)]

0

Xóa chỉ mục cụ thể (tôi đã xóa 16 và 21 khỏi ma trận)

import numpy as np
mat = np.arange(12,26)
a = [4,9]
del_map = np.delete(mat, a)
del_map.reshape(3,4)

Đầu ra:

array([[12, 13, 14, 15],
      [17, 18, 19, 20],
      [22, 23, 24, 25]])

0

Bạn cũng có thể sử dụng các bộ:

a = numpy.array([10, 20, 30, 40, 50, 60, 70, 80, 90])
the_index_list = [2, 3, 6]

the_big_set = set(numpy.arange(len(a)))
the_small_set = set(the_index_list)
the_delta_row_list = list(the_big_set - the_small_set)

a = a[the_delta_row_list]
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.