Thay thế các giá trị âm trong một mảng numpy


90

Có cách nào đơn giản để thay thế tất cả các giá trị âm trong một mảng bằng 0 không?

Tôi đang có một khối hoàn chỉnh về cách thực hiện bằng cách sử dụng mảng NumPy.

Ví dụ

a = array([1, 2, 3, -4, 5])

Tôi cần trở về

[1, 2, 3, 0, 5]

a < 0 cho:

[False, False, False, True, False]

Đây là nơi tôi bị mắc kẹt - cách sử dụng mảng này để sửa đổi mảng ban đầu.

Câu trả lời:


137

Bạn đã đi được nửa chặng đường. Thử:

In [4]: a[a < 0] = 0

In [5]: a
Out[5]: array([1, 2, 3, 0, 5])

89

Hãy thử numpy.clip:

>>> import numpy
>>> a = numpy.arange(-10, 10)
>>> a
array([-10,  -9,  -8,  -7,  -6,  -5,  -4,  -3,  -2,  -1,   0,   1,   2,
         3,   4,   5,   6,   7,   8,   9])
>>> a.clip(0, 10)
array([0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

Bạn chỉ có thể kẹp nửa dưới với clip(0).

>>> a = numpy.array([1, 2, 3, -4, 5])
>>> a.clip(0)
array([1, 2, 3, 0, 5])

Bạn chỉ có thể kẹp nửa trên với clip(max=n). (Điều này tốt hơn nhiều so với đề xuất trước đây của tôi, liên quan đến việc chuyển NaNđến tham số đầu tiên và sử dụng outđể ép buộc loại.):

>>> a.clip(max=2)
array([ 1,  2,  2, -4,  2])

Một cách tiếp cận thú vị khác là sử dụng where:

>>> numpy.where(a <= 2, a, 2)
array([ 1,  2,  2, -4,  2])

Cuối cùng, hãy xem xét câu trả lời của aix . Tôi thích clipcác thao tác đơn giản hơn vì nó tự ghi lại, nhưng câu trả lời của anh ấy thích hợp hơn cho các thao tác phức tạp hơn.


1
a.clip (0) là đủ vì OP chỉ muốn thay thế các giá trị âm. a.clip (0, 10) sẽ loại trừ bất kỳ điều gì trên 10.
Usagi

1
@Hiett - Tôi vừa thử và clip sẽ lấy một cái. Đầu tiên được giả định là min.
Usagi

phải là vấn đề về phiên bản với numpy - heres my ouptut: (Pdb) np.clip (w, 0) *** TypeError: clip () có ít nhất 3 đối số (2 đối số đã cho) - ngược lại: (Pdb) np.clip ( w, 0,1e6) mảng ([[0, 0,605]])
bph

1
@Hiett, phiên bản nào của numpy? Bạn đã thử phương pháp clip của a? Hàm tích hợp numpy.clipcho tôi lỗi tương tự, nhưng phương pháp thì không.
gửi

yeh nếu bạn gọi nó theo cách đó, nó có vẻ hoạt động, ví dụ: p w.clip (0) array ([[0, 0.605]]) - như thế nào?
bph

10

Một giải pháp Python tối giản khác mà không cần sử dụng numpy:

[0 if i < 0 else i for i in a]

Không cần xác định bất kỳ chức năng phụ nào.

a = [1, 2, 3, -4, -5.23, 6]
[0 if i < 0 else i for i in a]

sản lượng:

[1, 2, 3, 0, 0, 6]

1
Điều đó thật tuyệt - tôi đã tự hỏi cú pháp sẽ là gì để đặt câu lệnh if vào bên trong danh sách - tôi đã sai khi gắn nó sau vòng lặp for và chỉ sau đó nhận lại hai giá trị, ví dụ: [0, 0] cho ví dụ của bạn danh sách
bph

Tôi cũng làm như vậy khi ban đầu tôi học về khả năng hiểu danh sách và đang thử những thứ khác nhau để kiểm tra sự hiểu biết của mình - tôi cũng thấy có vẻ trực quan hơn khi đặt nó sau vòng lặp for. Tuy nhiên, bây giờ, điều này thực hiện :) Đặt nó trước foráp dụng nó cho mọi phần tử của danh sách, đặt nó sau, có nghĩa là chỉ khi điều kiện được đáp ứng thì nó mới được đưa vào danh sách kết quả.
Levon

2
@Hiett Nó chỉ sử dụng toán tử bậc ba ( i < 0 ? 0 : itrong C) bên trong một danh sách hiểu. Đặt dấu ngoặc để làm cho nó rõ ràng hơn [(0 if i < 0 else i) for i in a]. Đặt if after đang sử dụng phần bộ lọc của cấu trúc biểu thức danh sách. [(i) for i in a if i < 0]sẽ chỉ trả về danh sách các mục nhỏ hơn 0.
Paul S

2
Numpy rất mạnh mẽ vì nó thực hiện rất nhiều tính toán bằng mã c đã biên dịch và do đó nhanh hơn. So sánh phương pháp này với các phương pháp khác, tôi thấy sự khác biệt về hệ số tốc độ gần 10 lần (phương pháp này chậm hơn). Vì vậy, mặc dù trực quan và dễ đọc, nhưng điều này chắc chắn không dành cho những người chuyên sâu về tính toán.
rspencer

4

Và một khả năng khác:

In [2]: a = array([1, 2, 3, -4, 5])

In [3]: where(a<0, 0, a)
Out[3]: array([1, 2, 3, 0, 5])

2

Đây là một cách để làm điều đó trong Python mà không cần NumPy. Tạo một hàm trả về những gì bạn muốn và sử dụng khả năng hiểu danh sách hoặc hàm bản đồ .

>>> a = [1, 2, 3, -4, 5]

>>> def zero_if_negative(x):
...   if x < 0:
...     return 0
...   return x
...

>>> [zero_if_negative(x) for x in a]
[1, 2, 3, 0, 5]

>>> map(zero_if_negative, a)
[1, 2, 3, 0, 5]

1
đã đi xuống con đường này nhưng nghĩ rằng phải có một cách dễ dàng hơn, ít python hơn matlab để làm điều đó với numpy (vì dù sao tôi cũng đang sử dụng mảng chứ không phải danh sách). clip là hoàn hảo
bph
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.