ตัวเลข: แบ่งแต่ละแถวด้วยองค์ประกอบเวกเตอร์


119

สมมติว่าฉันมีอาร์เรย์จำนวนนับ:

data = np.array([[1,1,1],[2,2,2],[3,3,3]])

และฉันมี "เวกเตอร์:" ที่ตรงกัน

vector = np.array([1,2,3])

ฉันจะดำเนินการdataตามแต่ละแถวเพื่อลบหรือหารได้อย่างไรผลลัพธ์จึงเป็น:

sub_result = [[0,0,0], [0,0,0], [0,0,0]]
div_result = [[1,1,1], [1,1,1], [1,1,1]]

เรื่องสั้นสั้น ๆ : ฉันจะดำเนินการกับแต่ละแถวของอาร์เรย์ 2 มิติด้วยสเกลาร์ 1D ที่สอดคล้องกับแต่ละแถวได้อย่างไร

คำตอบ:


181

จัดให้เลย คุณเพียงแค่ต้องใช้None(หรืออีกทางเลือกหนึ่งnp.newaxis) ร่วมกับการออกอากาศ:

In [6]: data - vector[:,None]
Out[6]:
array([[0, 0, 0],
       [0, 0, 0],
       [0, 0, 0]])

In [7]: data / vector[:,None]
Out[7]:
array([[1, 1, 1],
       [1, 1, 1],
       [1, 1, 1]])

13
นี่คือเอกสาร
sazary


@ user108569 โดยใช้ numpy (1.18.1) เวอร์ชันล่าสุดNoneยังคงทำงานได้เทียบเท่ากับnp.newaxis. ฉันไม่แน่ใจว่าการตั้งค่าของคุณคืออะไรหรือปัญหาที่คุณพบ แต่คำตอบยังคงใช้ได้
JoshAdel

11

ดังที่ได้กล่าวไปแล้วการหั่นด้วยNoneหรือด้วยnp.newaxesเป็นวิธีที่ดีในการทำเช่นนี้ อีกทางเลือกหนึ่งคือการใช้การเปลี่ยนและการแพร่ภาพเช่นเดียวกับใน

(data.T - vector).T

และ

(data.T / vector).T

สำหรับอาร์เรย์มิติที่สูงขึ้นคุณอาจต้องการใช้swapaxesเมธอดของอาร์เรย์ NumPy หรือrollaxisฟังก์ชันNumPy มีหลายวิธีในการทำเช่นนี้

สำหรับคำอธิบายที่สมบูรณ์ยิ่งขึ้นเกี่ยวกับการแพร่ภาพโปรดดูที่ http://docs.scipy.org/doc/numpy/user/basics.broadcasting.html


4

โซลูชันของ JoshAdel ใช้ np.newaxis เพื่อเพิ่มมิติ ทางเลือกคือการใช้Reshape () เพื่อจัดมิติในการเตรียมตัวสำหรับการกระจายเสียง

data = np.array([[1,1,1],[2,2,2],[3,3,3]])
vector = np.array([1,2,3])

data
# array([[1, 1, 1],
#        [2, 2, 2],
#        [3, 3, 3]])
vector
# array([1, 2, 3])

data.shape
# (3, 3)
vector.shape
# (3,)

data / vector.reshape((3,1))
# array([[1, 1, 1],
#        [1, 1, 1],
#        [1, 1, 1]])

การทำ reshape () ช่วยให้มิติต่างๆจัดเรียงสำหรับการแพร่ภาพ:

data:            3 x 3
vector:              3
vector reshaped: 3 x 1

สังเกตว่าใช้ได้data/vectorแต่ไม่ได้รับคำตอบที่คุณต้องการ มันแบ่งแต่ละคอลัมน์ของarray(แทนของแต่ละแถว ) vectorโดยองค์ประกอบที่สอดคล้องกันของแต่ละ มันเป็นสิ่งที่คุณจะได้รับถ้าคุณเปลี่ยนโฉมหน้าอย่างชัดเจนvectorที่จะเป็นแทน1x33x1

data / vector
# array([[1, 0, 0],
#        [2, 1, 0],
#        [3, 1, 1]])
data / vector.reshape((1,3))
# array([[1, 0, 0],
#        [2, 1, 0],
#        [3, 1, 1]])

2

วิธี Pythonic ทำคือ ...

np.divide(data.T,vector).T

สิ่งนี้จะดูแลการก่อร่างใหม่และผลลัพธ์ก็อยู่ในรูปแบบทศนิยม ในคำตอบอื่น ๆ ผลลัพธ์จะอยู่ในรูปแบบจำนวนเต็มมน

#NOTE:จำนวนคอลัมน์ทั้งข้อมูลและเวกเตอร์ควรตรงกัน


หมายเหตุ: สิ่งนี้ไม่ได้ทำตามที่ OP ร้องขอ ผลลัพธ์สุดท้ายคืออาร์เรย์ ([[1., 0.5, 0.33333333], [2. , 1. , 0.66666667], [3. , 1.5, 1. ]]) อาจเป็น "Pythonic" แต่ไม่ถูกต้อง
Mark Cramer

1
@MarkCramer ขอบคุณครับ ฉันได้แก้ไขคำตอบของฉันเพื่อให้ได้ผลลัพธ์ที่ถูกต้อง
shantanu pathak

1

การเพิ่มคำตอบของ stackoverflowuser2010 ในกรณีทั่วไปคุณสามารถใช้ได้

data = np.array([[1,1,1],[2,2,2],[3,3,3]])

vector = np.array([1,2,3])

data / vector.reshape(-1,1)

สิ่งนี้จะเปลี่ยนเวกเตอร์ของคุณให้เป็นcolumn matrix/vectorไฟล์. ช่วยให้คุณสามารถดำเนินการตามองค์ประกอบได้ตามที่คุณต้องการ อย่างน้อยสำหรับฉันนี่เป็นวิธีที่ง่ายที่สุดในการดำเนินการและเนื่องจาก (ในกรณีส่วนใหญ่) numpy จะใช้มุมมองของหน่วยความจำภายในเดียวกันเพื่อการปรับรูปร่างใหม่ให้มีประสิทธิภาพเช่นกัน


นี่ควรเป็นคำตอบที่ได้รับการยอมรับ การสร้างเวกเตอร์คอลัมน์ด้วย.reshape(-1,1) เป็นวิธีที่ง่ายที่สุดในการใช้การกระจายเสียง
Paul Rougieux
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.