Histograma usando o gnuplot?

Eu sei como criar um histograma (apenas use “with boxes”) no gnuplot se meu arquivo .dat já tiver dados corretamente armazenados. Existe uma maneira de obter uma lista de números e o gnuplot fornecer um histograma com base nos intervalos e tamanhos de bandeja que o usuário fornece?

sim, e é rápido e simples, embora muito oculto:

binwidth=5 bin(x,width)=width*floor(x/width) plot 'datafile' using (bin($1,binwidth)):(1.0) smooth freq with boxes 

confira help smooth freq para ver por que isso faz um histograma

para lidar com intervalos basta definir a variável xrange.

Eu tenho algumas correções / adições à resposta muito útil do Born2Smile:

  1. Caixas vazias fizeram com que a checkbox da checkbox adjacente se estendesse incorretamente em seu espaço; evite isso usando a set boxwidth binwidth
  2. Na versão de Born2Smile, as checkboxs são renderizadas como centralizadas em seu limite inferior. Estritamente, eles devem se estender do limite inferior para o limite superior. Isso pode ser corrigido modificando-se a function bin : bin(x,width)=width*floor(x/width) + binwidth/2.0

Tenha muito cuidado: todas as respostas nesta página implicitamente estão tomando a decisão de onde o binning começa – a borda esquerda da checkbox mais à esquerda, se você quiser – fora das mãos do usuário. Se o usuário estiver combinando qualquer uma dessas funções para categorizar dados com sua própria decisão sobre o início da categorização (como é feito no blog que está vinculado acima), as funções acima estão todas incorretas. Com um ponto de partida arbitrário para o binning ‘Min’, a function correta é:

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

Você pode ver porque isso está correto sequencialmente (ajuda a desenhar algumas checkboxs e um ponto em algum lugar em uma delas). Subtraia Min do seu ponto de dados para ver a que distância está no intervalo de armazenamento. Em seguida, divida por largura de checkbox para que você esteja efetivamente trabalhando em unidades de ‘checkboxs’. Então, ‘chão’ o resultado para ir para a borda esquerda da checkbox, adicione 0,5 para ir para o meio da checkbox, multiplique pela largura para que você não trabalhe mais em unidades de checkboxs, mas em uma escala absoluta novamente, então, finalmente, adicione novamente a compensação Mínima subtraída no início.

Considere esta function em ação:

 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 

por exemplo, o valor 1.1 realmente cai no compartimento esquerdo:

  • essa function mapeia corretamente para o centro do escaninho esquerdo (0,75);
  • A resposta de Born2Smile, bin (x) = width * floor (x / width), mapeia incorretamente para 1;
  • Resposta do mas90, bin (x) = largura * piso (x / largura) + largura de bin / 2.0, mapeia incorretamente para 1.5.

A resposta do Born2Smile está correta apenas se os limites do bin ocorrerem em (n + 0.5) * binwidth (onde n é executado sobre números inteiros). A resposta do mas90 está correta apenas se os limites do bin ocorrerem em n * binwidth.

Você quer traçar um gráfico como este? insira a descrição da imagem aqui sim? Então você pode dar uma olhada no meu artigo do blog: http://gnuplot-surprising.blogspot.com/2011/09/statistic-analysis-and-histogram.html

Linhas chave do código:

 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 

Como de costume, o Gnuplot é uma ferramenta fantástica para traçar charts com aparência doce e pode ser feito para executar todos os tipos de cálculos. No entanto , pretende-se traçar dados em vez de servir como uma calculadora e muitas vezes é mais fácil usar um programa externo (por exemplo, Octave) para fazer os cálculos mais “complicados”, salvar esses dados em um arquivo e usar o Gnuplot para produzir o gráfico. Para o problema acima, verifique a function “hist” é Octave usando [freq,bins]=hist(data) , então plote isso no Gnuplot usando

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

Eu achei esta discussão extremamente útil, mas eu tenho experimentado alguns problemas de “arredondamento”.

Mais precisamente, usando uma largura de binário de 0,05, notei que, com as técnicas apresentadas acima, os pontos de dados que lêem 0,1 e 0,15 caem no mesmo compartimento. Este (comportamento obviamente indesejado) é mais provável devido à function “floor”.

A seguir, é minha pequena contribuição para tentar contornar isso.

 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 

Este método recursivo é para x> = 0; pode-se generalizar isso com mais declarações condicionais para obter algo ainda mais geral.

Nós não precisamos usar o método recursivo, pode ser lento. Minha solução é usar um rint de function definido pelo usuário com a function instrínseca int ou floor.

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

Esta function dará rint(0.0003/0.0001)=3 , enquanto int(0.0003/0.0001)=floor(0.0003/0.0001)=2 .

Por quê? Por favor, olhe Perl int function e zeros de preenchimento

Eu tenho uma pequena modificação na solução do Born2Smile.

Eu sei que isso não faz muito sentido, mas você pode querer apenas por precaução. Se seus dados forem inteiros e você precisar de um tamanho de escaninho flutuante (talvez para comparação com outro dataset ou densidade de plotagem em uma grade mais fina), será necessário adicionar um número random entre 0 e 1 no piso interno. Caso contrário, haverá picos devido ao erro de arredondamento. floor(x/width+0.5) não fará porque criará um padrão que não é fiel aos dados originais.

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

Com relação às funções de binning, não esperava o resultado das funções oferecidas até agora. Ou seja, se minha largura de banda é 0,001, essas funções estavam centralizando as checkboxs em 0,0005 pontos, enquanto eu sinto que é mais intuitivo ter as checkboxs cinputs em limites de 0,001.

Em outras palavras, eu gostaria de ter

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

A function binning que eu criei é

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

Aqui está um script para comparar algumas das funções de bin disponíveis para esta:

 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 } 

e aqui está a saída

  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