Tôi biết cách tạo biểu đồ (chỉ sử dụng "với hộp") trong gnuplot nếu tệp .dat của tôi đã có dữ liệu được đánh dấu đúng. Có cách nào để lấy danh sách các số và gnuplot cung cấp biểu đồ dựa trên phạm vi và kích thước bin mà người dùng cung cấp không?
Tôi biết cách tạo biểu đồ (chỉ sử dụng "với hộp") trong gnuplot nếu tệp .dat của tôi đã có dữ liệu được đánh dấu đúng. Có cách nào để lấy danh sách các số và gnuplot cung cấp biểu đồ dựa trên phạm vi và kích thước bin mà người dùng cung cấp không?
Câu trả lời:
vâng, và nó nhanh chóng và đơn giản mặc dù rất ẩn:
binwidth=5
bin(x,width)=width*floor(x/width)
plot 'datafile' using (bin($1,binwidth)):(1.0) smooth freq with boxes
kiểm tra help smooth freq
để xem tại sao ở trên làm cho một biểu đồ
để đối phó với các phạm vi chỉ cần đặt biến xrange.
set boxwidth binwidth
vào ở trên. Nó thực sự hữu ích cho tôi.
Tôi có một vài chỉnh sửa / bổ sung cho câu trả lời rất hữu ích của Born2Smile:
set boxwidth binwidth
bin
chức năng:bin(x,width)=width*floor(x/width) + width/2.0
bin(x,width)=width*floor(x/width) + binwidth/2.0
(tính toán dấu phẩy động)
bin(x,width)=width*floor(x/width) + width/2.0
. Nếu chúng ta đang vượt qua width
như một đối số, sau đó sử dụng nó. :-)
Hãy cẩn thận: tất cả các câu trả lời trên trang này đều hoàn toàn đưa ra quyết định nơi bắt đầu đóng thùng - cạnh trái của thùng ngoài cùng bên trái, nếu bạn muốn - ra khỏi tay người dùng. Nếu người dùng đang kết hợp bất kỳ chức năng nào trong số các chức năng này để tạo dữ liệu với quyết định của riêng mình về việc bắt đầu tạo thùng (như được thực hiện trên blog được liên kết ở trên) thì các chức năng trên đều không chính xác. Với điểm bắt đầu tùy ý để tạo thùng 'Min', chức năng chính xác là:
bin(x) = width*(floor((x-Min)/width)+0.5) + Min
Bạn có thể thấy lý do tại sao điều này là chính xác theo tuần tự (nó giúp vẽ một vài thùng và một điểm ở đâu đó trong một trong số chúng). Trừ Min khỏi điểm dữ liệu của bạn để xem phạm vi đóng gói của nó là bao xa. Sau đó chia cho băng thông để bạn làm việc hiệu quả trong các đơn vị 'thùng'. Sau đó, 'sàn' kết quả để đi đến cạnh bên trái của thùng đó, thêm 0,5 để vào giữa thùng, nhân với chiều rộng để bạn không còn làm việc trong các đơn vị thùng mà ở quy mô tuyệt đối một lần nữa, sau đó cuối cùng thêm lại vào phần bù Min mà bạn đã trừ khi bắt đầu.
Xem xét chức năng này trong hành động:
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
ví dụ: giá trị 1.1 thực sự rơi vào thùng bên trái:
Câu trả lời của Born2Smile chỉ đúng nếu ranh giới bin xảy ra tại (n + 0,5) * bin thong (trong đó n chạy trên số nguyên). Câu trả lời của mas90 chỉ đúng nếu ranh giới bin xảy ra ở n * bin thong.
Bạn có muốn vẽ đồ thị như thế này không? Đúng? Sau đó, bạn có thể xem bài viết trên blog của tôi: http://gnuplot-surprising.blogspot.com/2011/09/statistic-analysis-and-histogram.html
Các dòng chính từ mã:
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
Như thường lệ, Gnuplot là một công cụ tuyệt vời để vẽ đồ thị trông ngọt ngào và nó có thể được thực hiện để thực hiện tất cả các loại tính toán. Tuy nhiên , nó được dùng để vẽ dữ liệu thay vì dùng làm máy tính và thường sử dụng chương trình bên ngoài (ví dụ Octave) để thực hiện các phép tính "phức tạp" hơn, lưu dữ liệu này vào tệp, sau đó sử dụng Gnuplot để sản xuất đồ thị. Đối với vấn đề trên, hãy kiểm tra chức năng "hist" đang sử dụng Octave [freq,bins]=hist(data)
, sau đó vẽ biểu đồ này trong Gnuplot bằng cách sử dụng
set style histogram rowstacked gap 0
set style fill solid 0.5 border lt -1
plot "./data.dat" smooth freq with boxes
Tôi đã thấy cuộc thảo luận này cực kỳ hữu ích, nhưng tôi đã trải qua một số vấn đề "làm tròn".
Chính xác hơn, bằng cách sử dụng độ rộng 0,05, tôi nhận thấy rằng, với các kỹ thuật được trình bày ở trên, các điểm dữ liệu đọc 0,1 và 0,15 rơi vào cùng một thùng. Điều này (rõ ràng là hành vi không mong muốn) rất có thể là do chức năng "sàn".
Sau đây là đóng góp nhỏ của tôi để cố gắng phá vỡ điều này.
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
Phương thức đệ quy này là cho x> = 0; người ta có thể khái quát điều này với các tuyên bố có điều kiện hơn để có được một cái gì đó tổng quát hơn.
Chúng ta không cần sử dụng phương pháp đệ quy, nó có thể chậm. Giải pháp của tôi là sử dụng hàm do người dùng định nghĩa rint instesd của hàm Barsinsic int hoặc floor.
rint(x)=(x-int(x)>0.9999)?int(x)+1:int(x)
Chức năng này sẽ cung cấp rint(0.0003/0.0001)=3
, trong khi int(0.0003/0.0001)=floor(0.0003/0.0001)=2
.
Tại sao? Xin vui lòng nhìn vào chức năng Perl int và số không đệm
Tôi có một chút sửa đổi đối với giải pháp của Born2Smile.
Tôi biết điều đó không có nhiều ý nghĩa, nhưng bạn có thể muốn nó chỉ trong trường hợp. Nếu dữ liệu của bạn là số nguyên và bạn cần kích thước thùng phao (có thể để so sánh với một tập hợp dữ liệu khác hoặc mật độ lô trong lưới mịn hơn), bạn sẽ cần thêm một số ngẫu nhiên từ 0 đến 1 bên trong tầng. Nếu không, sẽ có đột biến do lỗi làm tròn. floor(x/width+0.5)
sẽ không làm vì nó sẽ tạo ra mẫu không đúng với dữ liệu gốc.
binwidth=0.3
bin(x,width)=width*floor(x/width+rand(0))
Đối với các chức năng tạo thùng, tôi không mong đợi kết quả của các chức năng được cung cấp cho đến nay. Cụ thể, nếu độ rộng băng thông của tôi là 0,001, các chức năng này đã tập trung vào các thùng trên 0,0005 điểm, trong khi tôi cảm thấy nó trực quan hơn khi đặt các thùng ở giữa ranh giới 0,001.
Nói cách khác, tôi muốn có
Bin 0.001 contain data from 0.0005 to 0.0014
Bin 0.002 contain data from 0.0015 to 0.0024
...
Hàm binning tôi nghĩ ra là
my_bin(x,width) = width*(floor(x/width+0.5))
Đây là tập lệnh để so sánh một số hàm bin được cung cấp với hàm này:
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
}
và đây là đầu ra
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