gnuplot을 사용하는 히스토그램?


202

내 .dat 파일에 이미 데이터가 제대로 비닝 된 경우 gnuplot에서 히스토그램을 만드는 방법 ( "상자 만 사용")을 알고 있습니다. 숫자 목록을 가져오고 gnuplot이 사용자가 제공하는 범위 및 빈 크기에 따라 히스토그램을 제공하도록하는 방법이 있습니까?


2
답을 얻지 못하면 그러한 일을하는 다른 도구가 있습니다. 여기에 루트 ( root.cern.ch )를 사용하는 다른 많은 사람들이 R을 사용하고 적어도 몇 가지 다른 옵션이 있습니다.
dmckee --- 전 변조 고양이 새끼

1
Bin은 히스토그램의 각 막대에 대해 함께 수집 된 값의 범위입니다. 각 구간에는 하한과 상한이 있으며 해당 범위의 값을 가진 모든 데이터가 해당 막대로 계산됩니다. Binned는 내 데이터 파일이 각 Bin 내에 몇 개의 데이터 포인트가 있는지에 따라 이미 구성되어 있으므로 히스토그램으로 플롯 할 수 있습니다.
mary

답변:


225

예, 매우 간단하지만 빠르고 간단합니다.

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 변수를 설정하십시오.


11
아래 @ChrisW의 답변은 Gnuplot에서 히스토그램을 만들고 싶은 사람에게 주목할 중요한 포인트를 제공한다고 생각합니다.
Abhinav

2
세트에 "누락 된"빈이없는 경우에만 작동합니다.이 함수는 누락 된 빈의 y- 값을 이전의 비결 실 빈의 y- 값으로 수정합니다. 이것은 매우 오해의 소지가 있습니다 !!!
PinkFloyd 2011

1
set boxwidth binwidth위에 추가하겠습니다 . 정말 도움이되었습니다.
Jaakko

90

Born2Smile의 매우 유용한 답변에 대한 몇 가지 수정 / 추가 사항이 있습니다.

  1. 빈 통으로 인해 인접한 통의 상자가 해당 공간으로 잘못 확장되었습니다. 이것을 사용하지 마십시오set boxwidth binwidth
  2. Born2Smile 버전에서 빈은 하한을 중심으로 렌더링됩니다. 엄격하게 그들은 하한에서 상한으로 확장해야합니다. bin기능을 수정하여 수정할 수 있습니다 .bin(x,width)=width*floor(x/width) + width/2.0

10
실제로 두 번째 부분은 bin(x,width)=width*floor(x/width) + binwidth/2.0(부동 소수점 계산)
bgw

8
당신은 의미 bin(x,width)=width*floor(x/width) + width/2.0합니다. width인수 로 전달 하는 경우이를 사용하십시오. :-)
Mitar

78

매우주의하십시오 :이 페이지의 모든 답변은 비닝이 시작되는 위치 (원하는 경우 가장 왼쪽 빈의 왼쪽 가장자리)를 사용자의 손에서 내재적으로 결정합니다. 사용자가 데이터를 비닝하기 위해 이러한 기능 중 하나를 비닝 시작 위치에 대한 자신의 결정과 결합하면 (위의 링크 된 블로그에서 수행됨) 위의 기능이 모두 올바르지 않습니다. 'Min'비닝을위한 임의의 시작점이있는 경우 올바른 기능은 다음과 같습니다.

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

이것이 순차적으로 올바른 이유를 알 수 있습니다 (몇 개의 쓰레기통과 그 안에 어딘가에 점을 그리는 데 도움이 됨). 데이터 포인트에서 Min을 빼서 비닝 범위까지 얼마나되는지 확인합니다. 그런 다음 '폭'단위로 효과적으로 작업 할 수 있도록 이진으로 나눕니다. 그런 다음 결과를 '바닥'으로 만들어 해당 빈의 왼쪽 가장자리로 이동하고 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 값은 실제로 왼쪽 빈에 해당합니다.

  • 이 함수는 왼쪽 빈 (0.75)의 중앙에 올바르게 매핑합니다.
  • Born2Smile의 답변 bin (x) = width * floor (x / width)는 1에 잘못 매핑됩니다.
  • mas90의 대답 bin (x) = width * floor (x / width) + binwidth / 2.0은 1.5에 잘못 매핑됩니다.

Binn 경계가 (n + 0.5) * binwidth (n이 정수를 넘음)에서 발생하는 경우 Born2Smile의 답은 정확합니다. bin 경계가 n * binwidth에서 발생하는 경우에만 mas90의 답이 정확합니다.


48

이와 같은 그래프를 그리시겠습니까? 여기에 이미지 설명을 입력하십시오 예? 그런 다음 내 블로그 기사를 볼 수 있습니다 : 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

10

평소와 같이, Gnuplot은 달콤한 그래프를 그리는 환상적인 도구이며 모든 종류의 계산을 수행 할 수 있습니다. 그러나 이는 계산기 역할을하기보다는 데이터를 플로팅하기위한 것이며 외부 프로그램 (예 : 옥타브)을 사용하여보다 "복잡한"계산을 수행하고이 데이터를 파일에 저장 한 다음 Gnuplot을 사용하여 생성하는 것이 더 쉽습니다. 그래프. 위의 문제에 대해서는 "hist"기능이 Octave using Octave인지 확인한 [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

7

이 토론은 매우 유용하지만 "반올림"문제가 발생했습니다.

더 정확하게는, 이진 폭 0.05를 사용하여, 위에서 제시된 기술에서, 0.1과 0.15를 읽는 데이터 포인트가 동일한 빈에 속한다는 것을 알았습니다. 이것은 (분명히 원치 않는 행동) "바닥"기능 때문일 가능성이 높습니다.

이후에 이것을 회피하려고 노력한 나의 작은 공헌이다.

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입니다. 더 일반적인 것을 얻기 위해 더 많은 조건문으로 이것을 일반화 할 수 있습니다.


6

재귀 방법을 사용할 필요가 없습니다. 느릴 수 있습니다. 내 솔루션은 내장 함수 int 또는 floor의 사용자 정의 함수 rint instesd를 사용하고 있습니다.

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.

왜? 제발 봐 펄 INT 기능과 패딩 제로


4

Born2Smile의 솔루션을 약간 수정했습니다.

나는 그것이 그다지 의미가 없다는 것을 알고 있습니다. 데이터가 정수이고 플로트 빈 크기가 필요한 경우 (다른 데이터 세트와 비교하거나 더 미세한 그리드의 플롯 밀도) 바닥 0과 1 사이의 난수를 추가해야합니다. 그렇지 않으면 반올림 오류로 인해 급증이 발생합니다. floor(x/width+0.5)원래 데이터에 맞지 않는 패턴을 생성하기 때문에 수행하지 않습니다.

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

1
그러한 상황이 발생하지 않았지만 나중에 발생할 수 있습니다. float sd를 사용하여 정규 분포 정수로 테스트하고 bin = 1 및 bin = sd로 히스토그램을 플로팅 할 수 있습니다. rand (0) 트릭을 사용하거나 사용하지 않고 얻은 것을 참조하십시오. 그의 원고를 검토 할 때 공동 작업자의 실수를 발견했습니다. 그의 결과는 예상대로 말도 안되는 것에서 아름다운 모습으로 바뀌었다.
path4

아마도 설명이 너무 짧아서 더 구체적인 테스트 사례가 없으면 설명을 이해할 수 없을 것입니다. downvote를 취소 할 수 있도록 답을 간단히 편집하겠습니다.)
Christoph

정규 분포의 정수를 고려하십시오. 그것들은 정수이기 때문에 많은 x / width가 동일합니다. 숫자가 1.3이라고 가정 해 봅시다. floor (x / width + 0.5)를 사용하면 모두 bin 1에 할당됩니다. 그러나 밀도 측면에서 1.3이 실제로 의미하는 것은 70 %는 bin 1에 있고 30 %는 bin 2에 있어야한다는 것입니다. rand (0 )는 적절한 밀도를 유지합니다. 따라서 0.5는 스파이크를 만들고 rand (0)은이를 유지합니다. hsxz에 의한 수치는 0.5 대신 rand (0)을 사용하면 훨씬 매끄 럽습니다. 그냥 반올림하지 않고 섭동없이 반올림합니다.
path4

3

비닝 함수와 관련하여 지금까지 제공된 함수의 결과를 기대하지 않았습니다. 즉, 내 바이너리 너비가 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
...

내가 비닝 기능은

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

제공된 bin 함수 중 일부를이 함수와 비교하는 스크립트는 다음과 같습니다.

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.