หากคุณต้องการหลีกเลี่ยงค่าใช้จ่ายหน่วยความจำของการแปลงเป็นชุดของ tuples หรือโครงสร้างข้อมูลอื่นที่คล้ายคลึงกันคุณสามารถใช้ประโยชน์จากอาร์เรย์ที่มีโครงสร้างของ numpy ได้
เคล็ดลับคือการดูอาร์เรย์ดั้งเดิมของคุณเป็นอาร์เรย์ที่มีโครงสร้างโดยที่แต่ละรายการสอดคล้องกับแถวของอาร์เรย์เดิม สิ่งนี้ไม่ได้ทำสำเนาและค่อนข้างมีประสิทธิภาพ
เป็นตัวอย่างรวดเร็ว:
import numpy as np
data = np.array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
ncols = data.shape[1]
dtype = data.dtype.descr * ncols
struct = data.view(dtype)
uniq = np.unique(struct)
uniq = uniq.view(data.dtype).reshape(-1, ncols)
print uniq
เพื่อให้เข้าใจถึงสิ่งที่เกิดขึ้นให้ดูที่ผลลัพธ์ของคนกลาง
เมื่อเราดูสิ่งต่าง ๆ เป็นอาร์เรย์ที่มีโครงสร้างองค์ประกอบแต่ละอย่างในอาร์เรย์จะเป็นแถวในอาร์เรย์เดิม (โดยทั่วไปมันเป็นโครงสร้างข้อมูลที่คล้ายกับรายการของ tuples)
In [71]: struct
Out[71]:
array([[(1, 1, 1, 0, 0, 0)],
[(0, 1, 1, 1, 0, 0)],
[(0, 1, 1, 1, 0, 0)],
[(1, 1, 1, 0, 0, 0)],
[(1, 1, 1, 1, 1, 0)]],
dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])
In [72]: struct[0]
Out[72]:
array([(1, 1, 1, 0, 0, 0)],
dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])
เมื่อเรารันnumpy.unique
เราจะได้อาร์เรย์ที่มีโครงสร้างกลับมา:
In [73]: np.unique(struct)
Out[73]:
array([(0, 1, 1, 1, 0, 0), (1, 1, 1, 0, 0, 0), (1, 1, 1, 1, 1, 0)],
dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<i8'), ('f3', '<i8'), ('f4', '<i8'), ('f5', '<i8')])
จากนั้นเราต้องดูเป็นอาร์เรย์ "ปกติ" ( _
เก็บผลลัพธ์ของการคำนวณครั้งล่าสุดipython
ซึ่งเป็นสาเหตุที่คุณเห็น_.view...
):
In [74]: _.view(data.dtype)
Out[74]: array([0, 1, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0])
จากนั้นเปลี่ยนรูปร่างกลับไปเป็นอาร์เรย์ 2D ( -1
เป็นตัวยึดตำแหน่งที่บอกให้ numpy คำนวณจำนวนแถวที่ถูกต้องให้จำนวนคอลัมน์):
In [75]: _.reshape(-1, ncols)
Out[75]:
array([[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
เห็นได้ชัดว่าถ้าคุณต้องการที่จะกระชับมากขึ้นคุณสามารถเขียนมันเป็น:
import numpy as np
def unique_rows(data):
uniq = np.unique(data.view(data.dtype.descr * data.shape[1]))
return uniq.view(data.dtype).reshape(-1, data.shape[1])
data = np.array([[1, 1, 1, 0, 0, 0],
[0, 1, 1, 1, 0, 0],
[0, 1, 1, 1, 0, 0],
[1, 1, 1, 0, 0, 0],
[1, 1, 1, 1, 1, 0]])
print unique_rows(data)
ซึ่งผลลัพธ์ใน:
[[0 1 1 1 0 0]
[1 1 1 0 0 0]
[1 1 1 1 1 0]]