ฉันรู้วิธีสร้างฮิสโตแกรม (เพียงแค่ใช้ "พร้อมกล่อง") ใน gnuplot หากไฟล์. dat ของฉันมีข้อมูลที่ถูกเจาะอย่างถูกต้องอยู่แล้ว มีวิธีในการรับรายการตัวเลขและให้ gnuplot จัดทำฮิสโตแกรมตามช่วงและขนาดถังที่ผู้ใช้ให้หรือไม่
ฉันรู้วิธีสร้างฮิสโตแกรม (เพียงแค่ใช้ "พร้อมกล่อง") ใน gnuplot หากไฟล์. dat ของฉันมีข้อมูลที่ถูกเจาะอย่างถูกต้องอยู่แล้ว มีวิธีในการรับรายการตัวเลขและให้ gnuplot จัดทำฮิสโตแกรมตามช่วงและขนาดถังที่ผู้ใช้ให้หรือไม่
คำตอบ:
ใช่และรวดเร็วและเรียบง่าย แต่ซ่อนอยู่มาก:
binwidth=5
bin(x,width)=width*floor(x/width)
plot 'datafile' using (bin($1,binwidth)):(1.0) smooth freq with boxes
ลองhelp smooth freq
ดูว่าทำไมข้างต้นทำฮิสโตแกรม
เพื่อจัดการกับช่วงเพียงแค่ตั้งค่าตัวแปร xrange
set boxwidth binwidth
ไปด้านบน มันมีประโยชน์จริง ๆ สำหรับฉัน
ฉันมีคำตอบที่เป็นประโยชน์อย่างมากของ Born2Smile ในการแก้ไข / เพิ่มเติม
set boxwidth binwidth
bin
ฟังก์ชั่น:bin(x,width)=width*floor(x/width) + width/2.0
bin(x,width)=width*floor(x/width) + binwidth/2.0
(การคำนวณจุดลอย)
bin(x,width)=width*floor(x/width) + width/2.0
คุณหมายถึง หากเราผ่านไปwidth
เป็นข้อโต้แย้งให้ใช้มัน :-)
ระวังให้ดี: คำตอบทั้งหมดในหน้านี้เป็นการตัดสินใจโดยปริยายว่าจุดเริ่มต้นของการเริ่มจากจุดใด - ขอบซ้ายของถังขยะซ้ายหากคุณต้องการ - ออกจากมือของผู้ใช้ หากผู้ใช้กำลังรวมฟังก์ชั่นใด ๆ เหล่านี้เข้ากับการตัดสินใจข้อมูลของตัวเองเกี่ยวกับการเริ่มต้นการทำสำเนา (ตามที่ทำในบล็อกที่เชื่อมโยงกับด้านบน) ฟังก์ชั่นด้านบนนั้นไม่ถูกต้องทั้งหมด ด้วยจุดเริ่มต้นโดยพลการสำหรับการ 'ต่ำสุด' ฟังก์ชันที่ถูกต้องคือ:
bin(x) = width*(floor((x-Min)/width)+0.5) + Min
คุณสามารถดูว่าทำไมสิ่งนี้ถึงถูกต้องตามลำดับ (ช่วยในการวาดถังขยะสองสามอันและจุดหนึ่งในหนึ่งในนั้น) ลบขั้นต่ำออกจากจุดข้อมูลของคุณเพื่อดูว่าอยู่ไกลแค่ไหนในขอบเขตของการ binning จากนั้นหารด้วยความเร็วเพื่อให้คุณทำงานได้อย่างมีประสิทธิภาพในหน่วยของ 'ถังขยะ' จากนั้น 'จัดเรียง' ผลลัพธ์เพื่อไปที่ขอบด้านซ้ายของถังขยะนั้นเพิ่ม 0.5 เพื่อไปที่กลางถังขยะคูณด้วยความกว้างเพื่อให้คุณไม่ได้ทำงานในหน่วยถังขยะอีกต่อไป อีกครั้งจากนั้นก็บวกกลับไปที่ค่าชดเชยขั้นต่ำที่คุณหักออกเมื่อเริ่มต้น
ลองใช้ฟังก์ชั่นนี้:
Min = 0.25 # where binning starts
Max = 2.25 # where binning ends
n = 2 # the number of bins
width = (Max-Min)/n # binwidth; evaluates to 1.0
bin(x) = width*(floor((x-Min)/width)+0.5) + Min
เช่นค่า 1.1 อยู่ในถังขยะด้านซ้ายอย่างแท้จริง:
คำตอบของ Born2Smile นั้นถูกต้องก็ต่อเมื่อขอบเขตของถังขยะเกิดขึ้นที่ (n + 0.5) * ความกว้าง (ที่ n วิ่งข้ามจำนวนเต็ม) คำตอบของ mas90 นั้นถูกต้องก็ต่อเมื่อมีขอบเขตของ bin เกิดขึ้นที่ n * binwidth
คุณต้องการพล็อตกราฟแบบนี้หรือไม่? ใช่? จากนั้นคุณสามารถดูบทความบล็อกของฉัน: http://gnuplot-surprising.blogspot.com/2011/09/statistic-analysis-and-histogram.html
สายสำคัญจากรหัส:
n=100 #number of intervals
max=3. #max value
min=-3. #min value
width=(max-min)/n #interval width
#function used to map a value to the intervals
hist(x,width)=width*floor(x/width)+width/2.0
set boxwidth width*0.9
set style fill solid 0.5 # fill style
#count and plot
plot "data.dat" u (hist($1,width)):(1.0) smooth freq w boxes lc rgb"green" notitle
ตามปกติแล้ว Gnuplot เป็นเครื่องมือที่ยอดเยี่ยมสำหรับการพล็อตกราฟที่ดูหวานและสามารถทำการคำนวณได้ทุกประเภท อย่างไรก็ตามมีจุดประสงค์ในการพล็อตข้อมูลแทนที่จะใช้เป็นเครื่องคิดเลขและมักจะใช้โปรแกรมภายนอก (เช่น Octave) เพื่อทำการคำนวณที่ "ซับซ้อน" มากขึ้นบันทึกข้อมูลนี้ในไฟล์แล้วใช้ Gnuplot เพื่อสร้าง กราฟ สำหรับปัญหาข้างต้นให้ตรวจสอบฟังก์ชั่น "hist" ที่ใช้เป็นอ็อกเท[freq,bins]=hist(data)
ฟจากนั้นพล็อตเรื่องนี้ใน Gnuplot โดยใช้
set style histogram rowstacked gap 0
set style fill solid 0.5 border lt -1
plot "./data.dat" smooth freq with boxes
ฉันพบการสนทนานี้มีประโยชน์อย่างยิ่ง แต่ฉันพบปัญหา "การปัดเศษ" บางอย่าง
แม่นยำยิ่งขึ้นด้วยการใช้ความกว้างของ 0.05 ฉันได้สังเกตเห็นว่าด้วยเทคนิคที่นำเสนอที่นี่ข้างต้นจุดข้อมูลที่อ่าน 0.1 และ 0.15 อยู่ในถังขยะเดียวกัน พฤติกรรมนี้ (พฤติกรรมที่ไม่ต้องการอย่างเห็นได้ชัด) มักเกิดจากฟังก์ชั่น "floor"
ต่อจากนี้ไปฉันมีส่วนร่วมเล็กน้อยในการพยายามหลีกเลี่ยงสิ่งนี้
bin(x,width,n)=x<=n*width? width*(n-1) + 0.5*binwidth:bin(x,width,n+1)
binwidth = 0.05
set boxwidth binwidth
plot "data.dat" u (bin($1,binwidth,1)):(1.0) smooth freq with boxes
วิธีการเรียกซ้ำนี้ใช้สำหรับ x> = 0; เราสามารถพูดคุยเรื่องนี้โดยมีเงื่อนไขเพิ่มเติมเพื่อให้ได้อะไรที่กว้างกว่า
เราไม่จำเป็นต้องใช้วิธีการเรียกซ้ำมันอาจจะช้า วิธีการแก้ปัญหาของฉันคือการใช้ฟังก์ชั่นที่ผู้ใช้กำหนดเองอินสแตนซ์ของฟังก์ชั่น instrinsic int หรือพื้น
rint(x)=(x-int(x)>0.9999)?int(x)+1:int(x)
ฟังก์ชั่นนี้จะช่วยให้ในขณะที่rint(0.0003/0.0001)=3
int(0.0003/0.0001)=floor(0.0003/0.0001)=2
ทำไม? โปรดดูฟังก์ชั่น Perl int และการเติมเต็มศูนย์
ฉันมีการดัดแปลงเล็กน้อยเพื่อแก้ปัญหาของ Born2Smile
ฉันรู้ว่ามันไม่สมเหตุสมผล แต่คุณอาจต้องการในกรณี หากข้อมูลของคุณเป็นจำนวนเต็มและคุณต้องการขนาดถังขยะ (อาจเปรียบเทียบกับชุดข้อมูลอื่นหรือความหนาแน่นของพล็อตในตารางปลีกย่อย) คุณจะต้องเพิ่มจำนวนสุ่มระหว่าง 0 ถึง 1 มิฉะนั้นจะมี spikes เนื่องจากข้อผิดพลาดในการปัดเศษขึ้น floor(x/width+0.5)
จะไม่ทำเพราะมันจะสร้างรูปแบบที่ไม่เป็นความจริงกับข้อมูลต้นฉบับ
binwidth=0.3
bin(x,width)=width*floor(x/width+rand(0))
ด้วยความเคารพต่อฟังก์ชั่น binning ฉันไม่ได้คาดหวังผลลัพธ์ของฟังก์ชั่นที่เสนอมาจนถึงตอนนี้ กล่าวคือถ้าความกว้างของฉันคือ 0.001 ฟังก์ชั่นเหล่านี้อยู่ตรงกลางของถังขยะที่ 0.0005 จุดในขณะที่ฉันรู้สึกว่ามันง่ายกว่าที่จะให้ถังขยะอยู่ที่ขอบเขต 0.001
กล่าวอีกนัยหนึ่งฉันต้องการที่จะมี
Bin 0.001 contain data from 0.0005 to 0.0014
Bin 0.002 contain data from 0.0015 to 0.0024
...
ฟังก์ชั่น binning ที่ฉันคิดขึ้นมาคือ
my_bin(x,width) = width*(floor(x/width+0.5))
ต่อไปนี้เป็นสคริปต์เพื่อเปรียบเทียบฟังก์ชั่นถังขยะที่นำเสนอกับฟังก์ชันนี้:
rint(x) = (x-int(x)>0.9999)?int(x)+1:int(x)
bin(x,width) = width*rint(x/width) + width/2.0
binc(x,width) = width*(int(x/width)+0.5)
mitar_bin(x,width) = width*floor(x/width) + width/2.0
my_bin(x,width) = width*(floor(x/width+0.5))
binwidth = 0.001
data_list = "-0.1386 -0.1383 -0.1375 -0.0015 -0.0005 0.0005 0.0015 0.1375 0.1383 0.1386"
my_line = sprintf("%7s %7s %7s %7s %7s","data","bin()","binc()","mitar()","my_bin()")
print my_line
do for [i in data_list] {
iN = i + 0
my_line = sprintf("%+.4f %+.4f %+.4f %+.4f %+.4f",iN,bin(iN,binwidth),binc(iN,binwidth),mitar_bin(iN,binwidth),my_bin(iN,binwidth))
print my_line
}
และนี่คือผลลัพธ์
data bin() binc() mitar() my_bin()
-0.1386 -0.1375 -0.1375 -0.1385 -0.1390
-0.1383 -0.1375 -0.1375 -0.1385 -0.1380
-0.1375 -0.1365 -0.1365 -0.1375 -0.1380
-0.0015 -0.0005 -0.0005 -0.0015 -0.0010
-0.0005 +0.0005 +0.0005 -0.0005 +0.0000
+0.0005 +0.0005 +0.0005 +0.0005 +0.0010
+0.0015 +0.0015 +0.0015 +0.0015 +0.0020
+0.1375 +0.1375 +0.1375 +0.1375 +0.1380
+0.1383 +0.1385 +0.1385 +0.1385 +0.1380
+0.1386 +0.1385 +0.1385 +0.1385 +0.1390