Histogram menggunakan gnuplot?


202

Saya tahu cara membuat histogram (cukup gunakan "dengan kotak") di gnuplot jika file .dat saya sudah memiliki data yang dikosongkan dengan benar. Apakah ada cara untuk mengambil daftar angka dan meminta gnuplot memberikan histogram berdasarkan rentang dan ukuran nampan yang disediakan pengguna?


2
Jika Anda tidak mendapatkan jawaban ada alat lain yang dimaksudkan untuk melakukan hal-hal seperti itu. Saya menggunakan Root ( root.cern.ch ) banyak orang lain di sini menggunakan R, dan setidaknya ada beberapa opsi lain.
dmckee --- ex-moderator kitten

1
Bin adalah rentang nilai yang dikumpulkan bersama untuk setiap bilah di histogram. Setiap nampan memiliki batas bawah dan atas, dan semua data dengan nilai dalam rentang itu akan dihitung ke bilah itu. Binned berarti bahwa file data saya sudah diatur oleh berapa banyak titik data yang termasuk dalam masing-masing bin sehingga siap untuk diplot sebagai histogram.
mary

Jawaban:


225

ya, dan ini cepat dan sederhana meskipun sangat tersembunyi:

binwidth=5
bin(x,width)=width*floor(x/width)

plot 'datafile' using (bin($1,binwidth)):(1.0) smooth freq with boxes

periksa help smooth frequntuk melihat mengapa hal di atas membuat histogram

untuk menangani rentang cukup atur variabel xrange.


11
Saya pikir jawaban @ ChrisW di bawah ini membawa poin penting untuk diperhatikan bagi siapa saja yang ingin membuat Histogram di Gnuplot.
Abhinav

2
Berhati-hatilah, ini hanya berfungsi jika tidak ada nampan "hilang" di set ... Fungsi ini memperbaiki nilai y dari nampan yang hilang ke nilai y dari nampan sebelumnya yang tidak hilang. Ini bisa sangat menyesatkan !!!
PinkFloyd

1
Saya akan menambahkan di set boxwidth binwidthatas. Itu sangat membantu saya.
Jaakko

90

Saya punya beberapa koreksi / tambahan untuk jawaban Born2Smile yang sangat berguna:

  1. Tempat sampah yang kosong menyebabkan kotak untuk tempat sampah yang berdekatan meluas ke ruangnya; hindari menggunakan iniset boxwidth binwidth
  2. Dalam versi Born2Smile, nampan-nampan diberikan sebagai terpusat pada batas bawah mereka. Ketat mereka harus memanjang dari batas bawah ke batas atas. Ini dapat diperbaiki dengan memodifikasi binfungsi:bin(x,width)=width*floor(x/width) + width/2.0

10
Sebenarnya bagian kedua itu seharusnya bin(x,width)=width*floor(x/width) + binwidth/2.0(perhitungan titik mengambang)
bgw

8
Maksudmu bin(x,width)=width*floor(x/width) + width/2.0. Jika kita memberikan widthargumen, gunakan itu. :-)
Mitar

78

Berhati-hatilah: semua jawaban di halaman ini secara implisit mengambil keputusan dari mana binning dimulai - tepi kiri bin paling kiri, jika Anda mau - keluar dari tangan pengguna. Jika pengguna menggabungkan salah satu dari fungsi-fungsi ini untuk data binning dengan keputusannya sendiri tentang di mana binning dimulai (seperti yang dilakukan di blog yang terhubung ke atas) fungsi-fungsi di atas semuanya salah. Dengan titik awal sembarang untuk binning 'Min', fungsi yang benar adalah:

bin(x) = width*(floor((x-Min)/width)+0.5) + Min

Anda dapat melihat mengapa ini benar secara berurutan (ini membantu untuk menggambar beberapa nampan dan titik di salah satu dari mereka). Kurangi Min dari titik data Anda untuk melihat seberapa jauh jarak binning itu. Kemudian bagi dengan lebar pita sehingga Anda dapat bekerja secara efektif dalam satuan 'sampah'. Kemudian 'letakkan' hasilnya untuk pergi ke tepi kiri tempat sampah itu, tambahkan 0,5 untuk pergi ke tengah tempat sampah, kalikan dengan lebar sehingga Anda tidak lagi bekerja di unit sampah tetapi dalam skala absolut lagi, lalu akhirnya tambahkan kembali pada offset Min yang Anda kurangi di awal.

Pertimbangkan fungsi ini dalam aksi:

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

misalnya nilai 1.1 benar-benar jatuh di tempat sampah kiri:

  • fungsi ini memetakannya dengan benar ke tengah tempat sampah kiri (0.75);
  • Jawaban Born2Smile, bin (x) = width * floor (x / width), salah memetakannya menjadi 1;
  • Jawaban mas90, bin (x) = width * floor (x / width) + binwidth / 2.0, salah memetakannya menjadi 1,5.

Jawaban Born2Smile hanya benar jika batas bin terjadi pada (n + 0,5) * binwidth (di mana n berjalan di atas bilangan bulat). Jawaban mas90 hanya benar jika batas bin terjadi pada n * binwidth.


48

Apakah Anda ingin merencanakan grafik seperti ini? masukkan deskripsi gambar di sini Iya? Kemudian Anda dapat melihat artikel blog saya: http://gnuplot-surprising.blogspot.com/2011/09/statistic-analysis-and-histogram.html

Baris kunci dari kode:

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

10

Seperti biasa, Gnuplot adalah alat yang fantastis untuk memplot grafik yang tampak manis dan dapat dibuat untuk melakukan segala macam perhitungan. Namun , ini dimaksudkan untuk memplot data daripada berfungsi sebagai kalkulator dan seringkali lebih mudah untuk menggunakan program eksternal (misalnya Octave) untuk melakukan perhitungan yang lebih "rumit", menyimpan data ini dalam file, kemudian menggunakan Gnuplot untuk menghasilkan grafik. Untuk masalah di atas, periksa fungsi "hist" adalah Oktaf menggunakan [freq,bins]=hist(data), kemudian plot ini di Gnuplot menggunakan

set style histogram rowstacked gap 0
set style fill solid 0.5 border lt -1
plot "./data.dat" smooth freq with boxes

7

Saya telah menemukan diskusi ini sangat berguna, tetapi saya telah mengalami beberapa masalah "pembulatan".

Lebih tepatnya, menggunakan binwidth 0,05, saya perhatikan bahwa, dengan teknik yang disajikan di sini, titik data yang bertuliskan 0,1 dan 0,15 jatuh di tempat yang sama. Ini (perilaku yang jelas tidak diinginkan) kemungkinan besar disebabkan oleh fungsi "lantai".

Akhirat adalah kontribusi kecil saya untuk mencoba mengelak dari ini.

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

Metode rekursif ini untuk x> = 0; seseorang dapat menggeneralisasi ini dengan pernyataan yang lebih bersyarat untuk mendapatkan sesuatu yang lebih umum.


6

Kita tidak perlu menggunakan metode rekursif, mungkin lambat. Solusi saya menggunakan fungsi yang ditentukan pengguna dan insting fungsi instrinsik int atau lantai.

rint(x)=(x-int(x)>0.9999)?int(x)+1:int(x)

Fungsi ini akan memberi rint(0.0003/0.0001)=3, sementara int(0.0003/0.0001)=floor(0.0003/0.0001)=2.

Mengapa? Silakan lihat fungsi Perl int dan padding nol


4

Saya punya sedikit modifikasi pada solusi Born2Smile.

Saya tahu itu tidak masuk akal, tetapi Anda mungkin ingin berjaga-jaga. Jika data Anda bilangan bulat dan Anda membutuhkan ukuran tempat sampah (mungkin untuk perbandingan dengan kumpulan data lain, atau kepadatan plot dalam kisi yang lebih halus), Anda perlu menambahkan angka acak antara 0 dan 1 di dalam lantai. Kalau tidak, akan ada lonjakan karena kesalahan pembulatan. floor(x/width+0.5)tidak akan melakukannya karena itu akan membuat pola yang tidak benar untuk data asli.

binwidth=0.3
bin(x,width)=width*floor(x/width+rand(0))

1
Anda belum mengalami situasi seperti itu, tetapi Anda mungkin nanti. Anda dapat mengujinya dengan bilangan bulat yang terdistribusi normal dengan float sd dan plot histogram dengan bin = 1, dan bin = sd Lihat apa yang Anda dapatkan dengan dan tanpa trik rand (0). Saya menangkap kesalahan kolaborator ketika meninjau naskahnya. Hasilnya berubah dari benar-benar omong kosong menjadi sosok cantik seperti yang diharapkan.
path4

Ok, mungkin penjelasannya sangat singkat, sehingga orang tidak dapat memahaminya tanpa uji kasus yang lebih konkret. Saya akan mengedit jawaban Anda sehingga saya dapat membatalkan downvote;)
Christoph

Pertimbangkan bilangan bulat dari distribusi normal. Karena mereka bilangan bulat, banyak dari mereka akan memiliki x / lebar yang sama. Katakanlah angka itu adalah 1.3. Dengan lantai (x / lebar + 0,5), semuanya akan ditugaskan ke nampan 1. Tetapi yang benar-benar berarti dalam hal kepadatan adalah bahwa 70% dari mereka harus di nampan 1 dan 30% di nampan 2. rand (0 ) menjaga kepadatan yang tepat. Jadi, 0,5 menciptakan paku dan rand (0) tetap benar Saya yakin angka dengan hsxz akan jauh lebih lancar menggunakan rand (0) daripada 0,5. Ini bukan hanya mengumpulkan, tetapi mengumpulkan tanpa gangguan.
path4

3

Sehubungan dengan fungsi binning, saya tidak mengharapkan hasil dari fungsi yang ditawarkan sejauh ini. Yaitu, jika binwidth saya adalah 0,001, fungsi-fungsi ini memusatkan nampan pada 0,0005 poin, sedangkan saya merasa lebih intuitif untuk memusatkan nampan pada batas 0,001.

Dengan kata lain, saya ingin memilikinya

Bin 0.001 contain data from 0.0005 to 0.0014
Bin 0.002 contain data from 0.0015 to 0.0024
...

Fungsi binning yang saya buat adalah

my_bin(x,width)     = width*(floor(x/width+0.5))

Berikut ini skrip untuk membandingkan beberapa fungsi nampan yang ditawarkan dengan yang ini:

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
}

dan inilah hasilnya

   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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.