LaurVas

Гистограммы в гнуплоте

gnuplot

Пример гистограммы

Гистограмма позволяет визуально оценить какую-то случайную величину: насколько она случайна, велик ли разброс и какой характер этого разброса. По форме гистограммы можно подобрать закон распределения случайной величины. Математическая статистика вообще классная штука — находит закономерности там, где их нет.

Ничего нового я не изобрёл, пример гистограммы можно найти на оф. сайте гнуплота. Просто сейчас мы подробно разберём построение гистограммы и как им пользоваться в личных целях.

Простая гистограмма

Данные, по которым будет построена гистограмма, должны располагаться в текстовом файле, по одному числу на строке. Пусть он будет называться distribution.txt, а скрипт, строящий график — histogram.plot.

histogram.plot
#!/usr/bin/gnuplot -persist
width=10
bin(x, s) = s*int(x/s) + width/2
set boxwidth width
plot 'distribution.txt' u (bin($1,width)):(1.0) \
s f w boxes fs solid 0.5 title 'гистограмма'

#!/usr/bin/gnuplot -persist — she-bang, работает только в *nix
width=10 — объявляем переменную для хранения ширины столбца гистограммы
bin(x, s) = s*int(x/s) + width/2 — функция определяет в какой из столбиков попадёт входное значение
set boxwidth width — задаём ширину столбца для рисования, используя переменную width
plot 'distribution.txt' — тут вроде понятно
u (bin($1,width)):(1.0) — по оси X откладываем результат функции bin() от первого столбца в файле, а по Y — просто единичку
s f — суммировать Y (smooth frequency)
w boxes — рисовать столбики (для эксперимента попробуйте lines, linespoints, points, impulses)
fs solid 0.5 — определяем стиль заливки столбиков (fillstyle) как сплошной (solid) с 50%-ной непрозрачностью
title 'гистограмма' — подпись в легенде

Теперь либо запускаем сам скрипт:

$ chmod +x histogram.plot
$ ./histogram.plot
</code>

либо скармливаем его гнуплоту:

$ gnuplot -persist histogram.plot
</code>

В любом случае получаем картинку:

Первая гистограмма

Симпатично, но стоит слегка поправить. Делаю width=100 и добавляю ограничение на диапазон иксов set xrange [:6000]. Ещё можно включить сетку: set grid.

Вторая гистограмма

Собственно, здесь я ожидал увидеть ассимметричное распределение. Так и получилось.

Внимательные читатели заметили, что диапазон по оси Y вырос почти на порядок. Высота каждого столбика показывает количество попаданий в диапазон, определяемый его шириной. Следовательно, чем уже столбик, тем меньше входных значений в него попадает.

Добавляем точки

Не знаю, как назвать эту модификацию. Просто покажу исходник и результат.

#!/usr/bin/gnuplot -persist
width=100
bin(x, s) = s*int(x/s) + width/2
set xrange [:6000]
set boxwidth width
set grid
plot 'distribution.txt' u (bin($1,width)):(1.0)s f w boxes \
fs solid 0.5 t 'гистограмма', "" u 1:(300*rand(0)-350) lt 1 notitle

Третья гистограмма

Каждая красная точка соответствует одному измерению. С ними хорошо заметны выбросы. Вот только в диапазоне 1000–2000 точек слишком много, от чего они сливаются в сплошную красную массу. Можно конечно растянуть полосу пошире, но мы пойдем другим путем.

#!/usr/bin/gnuplot -persist
width=100
bin(x, s) = s*int(x/s) + width/2
set xrange [:6000]
set boxwidth width
set grid
plot 'distribution.txt' u (bin($1,width)):(1.0) s f w boxes fs solid 0.5 title 'гистограмма', \
"" u 1:(300*rand(0)-350):(15) w circles lc rgb "red" fs transparent solid 0.05 noborder notitle

Четвёртая гистограмма

За счёт прозрачности кружочков получается красивый эффект: чем больше кружочков накладывается, тем краснее. Не могу сказать какой толк от них на этом графике, но подобным образом можно красиво визуализировать большие объёмы данных. Также такими точками можно строить гистограммы от двух переменных.

Заключение

Графики — это красивые картинки, которые зачастую оказываются информативнее голых чисел. Для того и были придуманы.

Получить гистограмму средствами гнуплота очень просто. Всё, что вам нужно сделать — это подготовить файл с числами для анализа и подрегулировать некоторые параметры. Никаких тайных знаний не нужно. Как видите, программирование — это совсем не страшно.