ขนาดช่องเก็บใน Matplotlib (ฮิสโตแกรม)


คำตอบ:


270

ที่จริงแล้วมันค่อนข้างง่าย: แทนที่จะเป็นจำนวนถังขยะที่คุณสามารถให้รายการด้วยขอบเขตถังขยะ สามารถแจกจ่ายได้อย่างไม่เท่าเทียมกันเช่นกัน:

plt.hist(data, bins=[0, 10, 20, 30, 40, 50, 100])

หากคุณต้องการให้มันกระจายเท่า ๆ กันคุณสามารถใช้ช่วง:

plt.hist(data, bins=range(min(data), max(data) + binwidth, binwidth))

เพิ่มไปยังคำตอบเดิม

บรรทัดข้างต้นใช้งานได้สำหรับdataเต็มไปด้วยจำนวนเต็มเท่านั้น ในฐานะที่เป็นmacrocosmeชี้ให้เห็นสำหรับลอยคุณสามารถใช้:

import numpy as np
plt.hist(data, bins=np.arange(min(data), max(data) + binwidth, binwidth))

20
แทนที่ range (... ) ด้วย np.arange (... ) เพื่อให้มันทำงานกับ float
macrocosme

6
ช่องว่างที่นี่คืออะไรคุณตั้งค่าไว้ก่อนหน้านี้ไหม
UserYmY

1
ผมเชื่อว่า binwidth (data.max() - data.min()) / number_of_bins_you_wantในตัวอย่างนี้อาจจะพบได้โดย: + binwidthอาจมีการเปลี่ยนแปลงที่จะเพียงแค่1จะทำให้เรื่องนี้เป็นตัวอย่างที่เข้าใจได้ง่ายขึ้น
Jarad

2
นอกจากวิธีแก้ปัญหาที่ยอดเยี่ยมของ CodingCat ด้านบนสำหรับข้อมูลโฟลตหากคุณต้องการแท่งกราฟฮิสโตแกรมกึ่งกลางรอบ x-ticks จำนวนเต็มแทนที่จะมีขอบเขตของแท่งที่ x-ticks ลองปรับแต่งต่อไปนี้: bins = np.arange (dmin - 0.5, dmax + 0.5 + แบนด์วิดท์, แบนด์วิดท์)
DaveW

3
ตัวเลือกlw = 5, color = "white"หรือแทรกช่องว่างสีขาวที่คล้ายกันระหว่างแท่ง
PatrickT

13

สำหรับ N bins ขอบของ bin จะถูกระบุโดยรายการของค่า N + 1 โดยที่ N แรกจะให้ขอบ bin ด้านล่างและ +1 จะให้ขอบด้านบนของ bin สุดท้าย

รหัส:

from numpy import np; from pylab import *

bin_size = 0.1; min_edge = 0; max_edge = 2.5
N = (max_edge-min_edge)/bin_size; Nplus1 = N + 1
bin_list = np.linspace(min_edge, max_edge, Nplus1)

โปรดทราบว่า linspace ผลิตอาร์เรย์จาก min_edge ถึง max_edge แบ่งออกเป็นค่า N + 1 หรือ N ถังขยะ


1
โปรดทราบว่าถังขยะรวมขอบล่างและไม่รวมขอบบนยกเว้นถังขยะ N + 1 (ล่าสุด) ซึ่งรวมทั้งสองขอบเขต
lukewitmer

4

L = max - minผมคิดว่าวิธีที่ง่ายก็จะไปคำนวณค่าต่ำสุดและสูงสุดของข้อมูลที่คุณมีการคำนวณแล้ว จากนั้นคุณหารLด้วยความกว้างช่องที่ต้องการ (ฉันสมมติว่านี่คือสิ่งที่คุณหมายถึงโดยขนาดถังขยะ) และใช้เพดานของค่านี้เป็นจำนวนของถังขยะ


นั่นคือสิ่งที่ฉันมีในใจขอบคุณ แค่สงสัยว่ามีวิธีที่ง่ายกว่านี้ แต่ดูเหมือนว่าจะขอบคุณ!
Sam Creamer

ใช้ตัวเลขกลมฉันไม่ได้ขนาดถังขยะด้วยวิธีนี้ ใครมีประสบการณ์
แบรด Urani

3

ฉันชอบสิ่งต่าง ๆ ที่จะเกิดขึ้นโดยอัตโนมัติและเพื่อให้ถังขยะตกอยู่ในค่า "ดี" ต่อไปนี้ดูเหมือนว่าจะทำงานได้ค่อนข้างดี

import numpy as np
import numpy.random as random
import matplotlib.pyplot as plt
def compute_histogram_bins(data, desired_bin_size):
    min_val = np.min(data)
    max_val = np.max(data)
    min_boundary = -1.0 * (min_val % desired_bin_size - min_val)
    max_boundary = max_val - max_val % desired_bin_size + desired_bin_size
    n_bins = int((max_boundary - min_boundary) / desired_bin_size) + 1
    bins = np.linspace(min_boundary, max_boundary, n_bins)
    return bins

if __name__ == '__main__':
    data = np.random.random_sample(100) * 123.34 - 67.23
    bins = compute_histogram_bins(data, 10.0)
    print(bins)
    plt.hist(data, bins=bins)
    plt.xlabel('Value')
    plt.ylabel('Counts')
    plt.title('Compute Bins Example')
    plt.grid(True)
    plt.show()

ผลลัพธ์มีช่องเก็บในช่วงเวลาที่ดีของขนาดช่องเก็บ

[-70. -60. -50. -40. -30. -20. -10.   0.  10.  20.  30.  40.  50.  60.]

คำนวณฮิสโตแกรมของถังขยะ


สิ่งที่ฉันมองหาอย่างยอดเยี่ยม! อย่างไรก็ตามในบางกรณี n_bins ถูกปัดเศษลงเนื่องจากความแม่นยำจุดลอยตัว เช่นสำหรับdesired_bin_size=0.05, min_boundary=0.850, max_boundary=2.05การคำนวณn_binsจะกลายเป็นint(23.999999999999993)ซึ่งผลใน 23 แทน 24 และดังนั้นจึงหนึ่งถังที่น้อยเกินไป การปัดเศษก่อนการแปลงจำนวนเต็มทำงานสำหรับฉัน:n_bins = int(round((max_boundary - min_boundary) / desired_bin_size, 0)) + 1
M. Schlenker

3

ฉันใช้ควอไทล์ในการทำชุดถังขยะและพอดีกับตัวอย่าง:

bins=df['Generosity'].quantile([0,.05,0.1,0.15,0.20,0.25,0.3,0.35,0.40,0.45,0.5,0.55,0.6,0.65,0.70,0.75,0.80,0.85,0.90,0.95,1]).to_list()

plt.hist(df['Generosity'], bins=bins, normed=True, alpha=0.5, histtype='stepfilled', color='steelblue', edgecolor='none')

ป้อนคำอธิบายรูปภาพที่นี่


1
ความคิดที่ดี. คุณสามารถเปลี่ยนรายการ quantiles โดยหรือnp.arange(0, 1.01, 0.5) np.linspace(0, 1, 21)ไม่มีขอบ แต่ฉันเข้าใจว่ากล่องมีพื้นที่เท่ากัน แต่มีความกว้างต่างกันในแกน X ใช่ไหม
Tomasz Gandor

2

ฉันมีปัญหาเดียวกันกับ OP (ฉันคิดว่า!) แต่ฉันไม่สามารถทำงานในแบบที่ Lastalda ระบุได้ ฉันไม่ทราบว่าฉันตีความคำถามถูกต้องหรือไม่ แต่ฉันได้พบวิธีแก้ไขปัญหาอื่นแล้ว

นี่คือวิธีที่ฉันทำ:

plt.hist([1,11,21,31,41], bins=[0,10,20,30,40,50], weights=[10,1,40,33,6]);

ซึ่งสร้างสิ่งนี้:

ภาพแสดงกราฟฮิสโตแกรมที่สร้างใน matplotlib

ดังนั้นพารามิเตอร์แรกโดยทั่วไปแล้ว 'เริ่มต้น' ถังขยะ - ฉันกำลังสร้างหมายเลขเฉพาะที่อยู่ในช่วงที่ฉันกำหนดไว้ในพารามิเตอร์ถังขยะ

ในการสาธิตให้ดูที่อาร์เรย์ในพารามิเตอร์แรก ([1,11,21,31,41]) และอาร์เรย์ 'bins' ในพารามิเตอร์ที่สอง ([0,10,20,30,40,50]) :

  • หมายเลข 1 (จากอาร์เรย์แรก) อยู่ระหว่าง 0 และ 10 (ในอาร์เรย์ 'ถังขยะ')
  • หมายเลข 11 (จากอาร์เรย์แรก) อยู่ระหว่าง 11 และ 20 (ในอาร์เรย์ 'ถังขยะ')
  • หมายเลข 21 (จากอาร์เรย์แรก) อยู่ระหว่าง 21 ถึง 30 (ในอาร์เรย์ 'ถังขยะ') เป็นต้น

จากนั้นฉันใช้พารามิเตอร์ 'น้ำหนัก' เพื่อกำหนดขนาดของถังขยะแต่ละอัน นี่คืออาร์เรย์ที่ใช้สำหรับพารามิเตอร์น้ำหนัก: [10,1,40,33,6]

ดังนั้น 0 ถึง 10 bin จะได้รับค่า 10, 11 ถึง 20 bin จะได้รับค่า 1, 21 ถึง 30 bin จะได้รับค่า 40 เป็นต้น


3
ฉันคิดว่าคุณมีความเข้าใจผิดขั้นพื้นฐานเกี่ยวกับการทำงานของฮิสโตแกรม มันคาดว่าข้อมูลดิบ ดังนั้นในตัวอย่างของคุณอาร์เรย์ข้อมูลของคุณควรมี 10 ค่าระหว่าง 0 ถึง 10, 1 ค่าระหว่าง 10 ถึง 20 และอื่น ๆ จากนั้นฟังก์ชั่นจะทำการสรุปและวาดภาพ สิ่งที่คุณทำข้างต้นเป็นวิธีแก้ปัญหาเนื่องจากคุณมีเงินก้อนอยู่แล้ว (ซึ่งคุณใส่เข้าไปในกราฟโดยใช้ตัวเลือก "น้ำหนัก" ผิด) หวังว่าสิ่งนี้จะช่วยลดความสับสน
CodingCat

-1

สำหรับฮิสโตแกรมที่มีค่า x จำนวนเต็มฉันได้ใช้

plt.hist(data, np.arange(min(data)-0.5, max(data)+0.5))
plt.xticks(range(min(data), max(data)))

ออฟเซ็ต 0.5 จัดกึ่งกลางของถังขยะบนค่าแกน x การplt.xticksโทรจะเพิ่มขีดสำหรับจำนวนเต็มทุกตัว

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