ฮิสโตแกรมจำนวนมหาศาลบนอาเรย์หลายมิติ

ด้วยรูปร่าง np.array (n_days, n_lat, n_lon) ฉันต้องการคำนวณฮิสโตแกรมที่มีถังคงที่สำหรับแต่ละเซลล์ lat-lon (เช่น การกระจายของค่ารายวัน)

วิธีแก้ไขปัญหาง่ายๆ คือการวนซ้ำเซลล์และเรียกใช้ np.histogram สำหรับแต่ละเซลล์::

bins = np.linspace(0, 1.0, 10)
B = np.rand(n_days, n_lat, n_lon)
H = np.zeros((n_bins, n_lat, n_lon), dtype=np.int32)
for lat in range(n_lat):
    for lon in range(n_lon):
        H[:, lat, lon] = np.histogram(A[:, lat, lon], bins=bins)[0]
# note: code not tested

แต่นี่ค่อนข้างช้า มีวิธีแก้ปัญหาที่มีประสิทธิภาพมากกว่าที่ไม่เกี่ยวข้องกับการวนซ้ำหรือไม่?

ฉันดู np.searchsorted เพื่อรับดัชนี bin สำหรับแต่ละค่าใน B จากนั้นใช้การจัดทำดัชนีแฟนซีเพื่ออัปเดต H::

bin_indices = bins.searchsorted(B)
H[bin_indices.ravel(), idx[0], idx[1]] += 1  # where idx is a index grid given by np.indices
# note: code not tested

แต่วิธีนี้ใช้ไม่ได้เนื่องจากตัวดำเนินการเพิ่มแบบแทนที่ (+=) ดูเหมือนจะไม่รองรับการอัปเดตหลายรายการของเซลล์เดียวกัน

ขอบคุณปีเตอร์


person Peter Prettenhofer    schedule 17.09.2013    source แหล่งที่มา
comment
ดูเหมือนว่า github.com/numpy/numpy/pull/2821 กล่าวถึงการจัดทำดัชนีแฟนซีและ แทนที่ปัญหา เหตุผลที่ numpy ไม่อนุญาตให้อัปเดตหลายรายการก็คือ a[idx] += 1 จะไม่เหมือนกับ a[idx] = a[idx] + 1   -  person Peter Prettenhofer    schedule 17.09.2013
comment
ใช้ np.histogram2d กับอาร์กิวเมนต์คำหลัก weights   -  person Jaime    schedule 17.09.2013
comment
@Jaime ฉันจะใช้ weights ได้อย่างไร ฉันไม่อยากทำฮิสโตแกรม 2 มิติ   -  person Peter Prettenhofer    schedule 19.09.2013
comment
นอกจากนี้ยังมีฟังก์ชัน np.histogramdd   -  person Jaime    schedule 19.09.2013


คำตอบ (2)


คุณสามารถใช้ numpy.apply_along_axis เพื่อกำจัดการวนซ้ำ

hist, bin_edges = apply_along_axis(lambda x: histogram(x, bins=bins), 0, B)
person Greg Whittier    schedule 18.09.2013
comment
@PeterPrettenhofer เพิ่งแก้ไขการพิมพ์ผิด แลมบ์ดามีตัวอักษรย้าย หวังว่านี่จะเหมาะกับคุณ - person Greg Whittier; 19.09.2013

อาจจะใช้งานได้?:

import numpy as np
n_days=31
n_lat=10
n_lon=10
n_bins=10
bins = np.linspace(0, 1.0, n_bins)
B = np.random.rand(n_days, n_lat, n_lon)


# flatten to 1D
C=np.reshape(B,n_days*n_lat*n_lon)
# use digitize to get the index of the bin to which the numbers belong
D=np.digitize(C,bins)-1
# reshape the results back to the original shape
result=np.reshape(D,(n_days, n_lat, n_lon))
person Raphael Roth    schedule 17.09.2013
comment
สิ่งนี้ทำให้ฉันโดยพื้นฐานแล้วเหมือนกับ bins.searchsorted(B) ซึ่งเป็นอาร์เรย์ของรูปร่าง (n_days, n_lat, n_lon) แต่ส่วนที่ยุ่งยากคือวิธีแปลงมันเป็น (n_bins, n_lat, n_lon) - person Peter Prettenhofer; 17.09.2013