แทนที่ค่าลบในอาร์เรย์จำนวนนับ


91

มีวิธีง่ายๆในการแทนที่ค่าลบทั้งหมดในอาร์เรย์ด้วย 0 หรือไม่?

ฉันมีบล็อกที่สมบูรณ์เกี่ยวกับวิธีการใช้อาร์เรย์ NumPy

เช่น

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

ฉันต้องกลับ

[1, 2, 3, 0, 5]

a < 0 ให้:

[False, False, False, True, False]

นี่คือจุดที่ฉันติดอยู่ - วิธีใช้อาร์เรย์นี้เพื่อแก้ไขอาร์เรย์ดั้งเดิม

คำตอบ:


139

คุณอยู่ครึ่งทางแล้ว ลอง:

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

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

90

ลอง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])

clip(0)คุณสามารถคลิปเพียงครึ่งล่างด้วย

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

clip(max=n)คุณสามารถคลิปเพียงครึ่งบนกับ (นี่ดีกว่าคำแนะนำก่อนหน้าของฉันมากซึ่งเกี่ยวข้องกับการส่งผ่านNaNไปยังพารามิเตอร์แรกและใช้outเพื่อบังคับประเภท):

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

อีกแนวทางที่น่าสนใจคือการใช้where:

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

สุดท้ายพิจารณาคำตอบของaix ฉันชอบclipการดำเนินการที่เรียบง่ายเนื่องจากเป็นการจัดทำเอกสารด้วยตนเอง แต่คำตอบของเขาเหมาะสำหรับการดำเนินการที่ซับซ้อนมากกว่า


1
a.clip (0) จะเพียงพอเนื่องจาก OP ต้องการแทนที่ค่าลบ a.clip (0, 10) จะไม่รวมสิ่งที่อยู่เหนือ 10
Usagi

1
@Hiett - ฉันเพิ่งลองและคลิปจะใช้เวลาหนึ่ง ขั้นแรกจะถือว่าขั้นต่ำ
Usagi

ต้องเป็นปัญหาเกี่ยวกับเวอร์ชันที่มี numpy - heres my ouptut: (Pdb) np.clip (w, 0) *** TypeError: clip () ใช้เวลาอย่างน้อย 3 อาร์กิวเมนต์ (ให้ 2 รายการ) - ในขณะที่: (Pdb) np.clip ( w, 0,1e6) array ([[0. , 0.605]])
bph

1
@Hiett รุ่นnumpyอะไร? ลองดูคลิปวิธีการของa? ฟังก์ชั่นในตัวnumpy.clipทำให้ฉันมีข้อผิดพลาดเหมือนกัน แต่วิธีนี้ไม่ทำ
ส่ง

ใช่ถ้าคุณเรียกมันแบบนั้นว่ามันใช้งานได้เช่น p w.clip (0) array ([[0. , 0.605]]) - queer อย่างไร
bph

10

อีกหนึ่งโซลูชัน Python ที่เรียบง่ายโดยไม่ต้องใช้ numpy:

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

ไม่จำเป็นต้องกำหนดฟังก์ชันเสริมใด ๆ

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

ผลตอบแทน:

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

1
นั่นเป็นสิ่งที่ดี - ฉันสงสัยว่าไวยากรณ์จะเป็นอย่างไรในการใส่คำสั่ง if ในความเข้าใจรายการ - ฉันทำผิดโดยติดมันไว้หลัง for loop จากนั้นจึงได้รับสองค่ากลับมาเช่น [0, 0] สำหรับตัวอย่างของคุณ รายการ
bph

ฉันทำแบบเดียวกันกับตอนแรกที่ฉันเรียนรู้เกี่ยวกับความเข้าใจในรายการและพยายามทำสิ่งต่างๆเพื่อทดสอบความเข้าใจของฉัน - ดูเหมือนว่าจะใช้งานง่ายกว่าที่จะวางไว้หลัง for loop สำหรับฉันด้วย แม้ว่าตอนนี้จะทำ :) การวางไว้ก่อนforนำไปใช้กับทุกองค์ประกอบของรายการการวางไว้ข้างหลังหมายความว่าเฉพาะเมื่อตรงตามเงื่อนไขเท่านั้นจึงจะเข้าสู่รายการผลลัพธ์
Levon

2
@Hiett เป็นเพียงการใช้ตัวดำเนินการ ternary ( i < 0 ? 0 : iใน C) ในการทำความเข้าใจรายการ [(0 if i < 0 else i) for i in a]วงเล็บใส่ในที่จะทำให้มันชัดเจน การใส่ if after เป็นการใช้ส่วนกรองของโครงสร้างนิพจน์รายการ [(i) for i in a if i < 0]จะส่งคืนเฉพาะรายการที่มีค่าน้อยกว่าศูนย์
Paul S

2
Numpy มีประสิทธิภาพมากเนื่องจากทำการคำนวณโดยใช้โค้ด c ที่คอมไพล์แล้วจึงเร็วกว่า เมื่อเปรียบเทียบวิธีนี้กับวิธีอื่นฉันพบความแตกต่างของปัจจัยความเร็วเกือบ 10 เท่า (ช้ากว่า) ดังนั้นในขณะที่ใช้งานง่ายและอ่านง่าย แต่ก็ไม่เหมาะสำหรับการคำนวณอย่างเข้มข้น
rspencer


2

นี่คือวิธีทำใน Python โดยไม่มี NumPy สร้างฟังก์ชันที่ส่งคืนสิ่งที่คุณต้องการและใช้การทำความเข้าใจรายการหรือฟังก์ชันแผนที่

>>> 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
ได้ไปตามเส้นทางนี้ แต่คิดว่าจะต้องมีวิธี python ที่ง่ายกว่าและง่ายกว่ามากขึ้นกว่าที่จะทำกับ numpy (เนื่องจากฉันใช้อาร์เรย์มากกว่ารายการอยู่ดี) คลิปสมบูรณ์แบบ
bph
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.