Читая топик на хабре «Госдума представила доходы депутатов в новом виде», я решил, что данные по доходам депутатов стоят визуализации. Когда-то знакомство с темой «Визуализация данных» у меня началось с языка Processing, поэтому в качестве инструмента выступал именно он. Ниже фрагмент одной из первых картинок, а дальше можно познакомиться с тем, что такое Treemapping и как его готовить на Processing'е.
![](https://habrastorage.org/r/w1560/getpro/geektimes/post_images/c9c/d08/d08/c9cd08d08645f321e22d3cb96dad98d1.png)
Одна из лучших книг по визуализации данных для меня — это «Visualizing Data» Бена Фрая, небольшая по объему книга от одного из создателей Processing'а. Эта книга убивает сразу двух зайцев: в ней хорошо рассказано о принципах визуализации информации, плюс рассказывается, как для этого использовать язык Processing. Про Processing на Хабре уже писали, здесь и здесь. Сейчас доступна уже версия 2.0a4 (правда пока- альфа). В первой главе «Visualizing Data» Бен Фрай описывает семь этапов визуализации данных: получение данных, разбор данных, фильтрация лишних данных, обработка данных (например нахождение минимума и максимума), выбор представления данных, совершенствование этого представления, и последним пунктом идет добавление интерактива. Также он указывает, что этот процесс не всегда последовательный и часто приходится возвращаться на предыдущие этапы.
![](https://habrastorage.org/r/w780q1/getpro/geektimes/post_images/e9d/36d/08f/e9d36d08f1da08e72681ba955e259ee0.jpg)
Первым пунктом, естественно, идет получение самих данных. После просмотра страниц нескольких депутатов на сайте Думы стало ясно, что в url меняется только число — методом тыка было установлено, что нужный диапазон лежит в пределах [23494 — 23964], http://www.duma.gov.ru/structure/deputies/23494/ до http://www.duma.gov.ru/structure/deputies/23964/. На самой странице мне были нужны данные принадлежности к определенной фракции и информация по доходам. Данные я выкачал с помощью программы на С# (поскольку она у меня уже была), но это сделать не составит труда с помощью какого-нибудь своего скрипта. Правда, зайдя на следующий день на сайт Думы, я информации о доходах депутатов почему-то не увидел — не знаю, что это было — с работы и потом в другие дни все было на месте. Но я отвлекся. Первый пункт был выполнен — данные получены. Настала пора их визуализировать, и я решил начать со столбиковой диаграммы, поскольку ее достаточно просто сделать.
![Доходы депутатов за 2010 год](https://habrastorage.org/r/w1560/getpro/geektimes/post_images/ae4/394/277/ae4394277e7ab63f6cd50f42aeb253ed.png)
Картинка хорошо показывает, что основная масса депутатов получает приблизительно одни и те же деньги и что есть часть депутатов, которая получает на порядок больше. Минусы такой диаграммы: она не очень подходит для сравнения около 450 показателей. Помимо этого сильный разброс в значениях доходов делает маленькие значения неразличимыми. Можно, конечно, сделать шкалу логарифмической, но тогда потеряется визуальная интрига сравнения почти двух миллиардов с двумя миллионами. Хорошо — раз сопоставление показателей по соответствующей длине столбика работает плохо — надо сравнивать площади! Рисуем вместо столбиков кружочки:
![null](https://habrastorage.org/r/w1560/getpro/geektimes/post_images/280/264/667/2802646670fc2898d82fd2e5ceefda33.png)
Кружки не впечатляют — заменяем на квадраты:
![Пример Treemap](https://habrastorage.org/r/w1560/getpro/geektimes/post_images/259/a11/be6/259a11be67d99e4197d2f0adbb4e5880.png)
Как будто лучше. Сразу почему-то вспомнилась картинка с xkcd. И тут мне приходит на ум еще один вариант — treemap.
Treemap — изобретение гуру в Information Visualisation- Ben Shneiderman'а. Бен Шнайдерман в 1990 году задался вопросом, какие файлы занимают наибольшее место на жестком диске (в лаборатории, где он работал, 14 пользователей пользовались диском на 80 Mbyte). Бен начал думать над компактной визуализацией древовидной структуры папок и файлов — так ему пришла в голову диаграмма, которую впоследствии назвали Treemap. Подробнее про историю Treemapping'а можно почитать здесь: в конце статьи есть множество примеров использования этого типа визуализации. А в книге «Visualizing Data» целая глава посвящена Treemap. В дистрибутив Processing'а включены примеры к этой книге и есть два примера, посвященные Treemap. В обоих примерах используется библиотека Treemap — это измененная для работы с Processing'ом версия Java библиотеки. В этой библиотеке присутствуют несколько алгоритмов разбивки пространства на прямоугольники: slice-and-dice, pivot-by-middle, pivot-by-size, pivot-by-split-size и squarified layout. Сравнить работу разных алгоритмов можно здесь (требуется Java-плагин). Картинка, которую выдает «Squarified layout», по моему мнению, самая приятная для глаза. Этот алгоритм стремится так построить прямоугольники, чтобы их форма была как можно ближе к квадратам. Описание алгоритма «Squarified layout» приводится в статье Jack van Wijk'а. Для начала работы с библиотекой необходимо познакомиться с тремя классами из библиотеки: SimpleMapItem, MapModel и Treemap. Класс SimpleMapItem представляет одну ячейку, MapModel хранит в массиве список ячеек, а класс Treemap строит саму визуализацию, принимая в конструкторе объект типа MapModel и координаты границ диаграммы. Еще в объекте Treemap хранится объект MapLayout, который задает реализацию алгоритма разбивки. По умолчанию в Treemap используется алгоритм pivot-by-split-size, но ничто не мешает указать другой алгоритм с помощью функции: setLayout(MapLayout algorithm). Итак, в общих чертах, чтобы получить Treemap визуализацию в Processing'е, создаем классы DeputatItem и DeputatMap, реализующие интерфейсы SimpleMapItem и MapMode соответственно. В SimpleMapItem есть параметр size, который отвечает за размер прямоугольника в treemap, ему будем присваивать количество заработанных депутатом денег.
Читаем данные и сохраняем их в объекте DeputatItem, который реализует интерфейс SimpleMapItem. Созданный объект с информацией о депутате добавляем в объект DeputatMap (реализация интерфейса MapModel).
Создаем объект Treemap, отдавая ему в качестве параметров DeputatMap, и размеры прямоугольника, в котором строить диаграмму.
Предыдущий код выполняются в функции Processing'а setup(), а в функции Processing'а draw() вызываем функцию draw() объекта treemap.
Если каждому депутату задать цвет в соответствии с партией, к которой он принадлежит, и вывести информацию по депутатам в тех ячейках, размер которых это позволяет, то мы получим такую картинку:
![null](http://artprocessing.ru/wp-content/uploads/2012/01/DumaVFirstTry.png)
Я решил сгруппировать депутатов, принадлежащих к одной партии: для этого нужно добавить еще один уровень иерархии — партии. Схематично структуру дерева, полученную на предыдущем этапе, можно представить так: Дума->депутаты, добавив партии получим: Дума->партии->депутаты. Для такой схемы понадобятся еще два класса PartyItem (реализация интерфейса SimpleMapItem) и PartyMap (реализация интерфейса MapModel). После аналогичных шагов по созданию treemap получается такая картинка:
![null](http://artprocessing.ru/wp-content/uploads/2012/01/DumaV2010Money.png)
![null](http://artprocessing.ru/wp-content/uploads/2012/01/DumaVLegenda.png)
Картинки дают понять общую структуру распределения доходов, но найти конкретного депутата по картинке, к сожалению, не получится. Для этого можно воспользоваться интерактивной версией или скачать приложение для windows, linux, mac os, или запустить в процессинге, скачав исходный код.
P. S. Treemap можно строить не только в Processing'е. Natan Yu, автор блога Flowing data, пропагандирует такой подход к визуализации информации: работаем с данными в программе статистического анализа- R, полученное изображение потом доводим до ума в Иллюстраторе. Натан недавно выпустил книгу, в которой подробно описан такой подход. В R есть специальная функция для построения Treemap, для интересующихся сслылка на топик в блоге Натана.
Есть также JavaScript реализации:
Google Chart Tools Treemap;
d3.js Treemap;
JavaScript InfoVis Toolkit Treemap.
![](https://habrastorage.org/getpro/geektimes/post_images/c9c/d08/d08/c9cd08d08645f321e22d3cb96dad98d1.png)
Одна из лучших книг по визуализации данных для меня — это «Visualizing Data» Бена Фрая, небольшая по объему книга от одного из создателей Processing'а. Эта книга убивает сразу двух зайцев: в ней хорошо рассказано о принципах визуализации информации, плюс рассказывается, как для этого использовать язык Processing. Про Processing на Хабре уже писали, здесь и здесь. Сейчас доступна уже версия 2.0a4 (правда пока- альфа). В первой главе «Visualizing Data» Бен Фрай описывает семь этапов визуализации данных: получение данных, разбор данных, фильтрация лишних данных, обработка данных (например нахождение минимума и максимума), выбор представления данных, совершенствование этого представления, и последним пунктом идет добавление интерактива. Также он указывает, что этот процесс не всегда последовательный и часто приходится возвращаться на предыдущие этапы.
![](https://habrastorage.org/getpro/geektimes/post_images/e9d/36d/08f/e9d36d08f1da08e72681ba955e259ee0.jpg)
Первым пунктом, естественно, идет получение самих данных. После просмотра страниц нескольких депутатов на сайте Думы стало ясно, что в url меняется только число — методом тыка было установлено, что нужный диапазон лежит в пределах [23494 — 23964], http://www.duma.gov.ru/structure/deputies/23494/ до http://www.duma.gov.ru/structure/deputies/23964/. На самой странице мне были нужны данные принадлежности к определенной фракции и информация по доходам. Данные я выкачал с помощью программы на С# (поскольку она у меня уже была), но это сделать не составит труда с помощью какого-нибудь своего скрипта. Правда, зайдя на следующий день на сайт Думы, я информации о доходах депутатов почему-то не увидел — не знаю, что это было — с работы и потом в другие дни все было на месте. Но я отвлекся. Первый пункт был выполнен — данные получены. Настала пора их визуализировать, и я решил начать со столбиковой диаграммы, поскольку ее достаточно просто сделать.
![Доходы депутатов за 2010 год](https://habrastorage.org/getpro/geektimes/post_images/ae4/394/277/ae4394277e7ab63f6cd50f42aeb253ed.png)
Картинка хорошо показывает, что основная масса депутатов получает приблизительно одни и те же деньги и что есть часть депутатов, которая получает на порядок больше. Минусы такой диаграммы: она не очень подходит для сравнения около 450 показателей. Помимо этого сильный разброс в значениях доходов делает маленькие значения неразличимыми. Можно, конечно, сделать шкалу логарифмической, но тогда потеряется визуальная интрига сравнения почти двух миллиардов с двумя миллионами. Хорошо — раз сопоставление показателей по соответствующей длине столбика работает плохо — надо сравнивать площади! Рисуем вместо столбиков кружочки:
![null](https://habrastorage.org/getpro/geektimes/post_images/280/264/667/2802646670fc2898d82fd2e5ceefda33.png)
Кружки не впечатляют — заменяем на квадраты:
![Пример Treemap](https://habrastorage.org/getpro/geektimes/post_images/259/a11/be6/259a11be67d99e4197d2f0adbb4e5880.png)
Как будто лучше. Сразу почему-то вспомнилась картинка с xkcd. И тут мне приходит на ум еще один вариант — treemap.
Treemap — изобретение гуру в Information Visualisation- Ben Shneiderman'а. Бен Шнайдерман в 1990 году задался вопросом, какие файлы занимают наибольшее место на жестком диске (в лаборатории, где он работал, 14 пользователей пользовались диском на 80 Mbyte). Бен начал думать над компактной визуализацией древовидной структуры папок и файлов — так ему пришла в голову диаграмма, которую впоследствии назвали Treemap. Подробнее про историю Treemapping'а можно почитать здесь: в конце статьи есть множество примеров использования этого типа визуализации. А в книге «Visualizing Data» целая глава посвящена Treemap. В дистрибутив Processing'а включены примеры к этой книге и есть два примера, посвященные Treemap. В обоих примерах используется библиотека Treemap — это измененная для работы с Processing'ом версия Java библиотеки. В этой библиотеке присутствуют несколько алгоритмов разбивки пространства на прямоугольники: slice-and-dice, pivot-by-middle, pivot-by-size, pivot-by-split-size и squarified layout. Сравнить работу разных алгоритмов можно здесь (требуется Java-плагин). Картинка, которую выдает «Squarified layout», по моему мнению, самая приятная для глаза. Этот алгоритм стремится так построить прямоугольники, чтобы их форма была как можно ближе к квадратам. Описание алгоритма «Squarified layout» приводится в статье Jack van Wijk'а. Для начала работы с библиотекой необходимо познакомиться с тремя классами из библиотеки: SimpleMapItem, MapModel и Treemap. Класс SimpleMapItem представляет одну ячейку, MapModel хранит в массиве список ячеек, а класс Treemap строит саму визуализацию, принимая в конструкторе объект типа MapModel и координаты границ диаграммы. Еще в объекте Treemap хранится объект MapLayout, который задает реализацию алгоритма разбивки. По умолчанию в Treemap используется алгоритм pivot-by-split-size, но ничто не мешает указать другой алгоритм с помощью функции: setLayout(MapLayout algorithm). Итак, в общих чертах, чтобы получить Treemap визуализацию в Processing'е, создаем классы DeputatItem и DeputatMap, реализующие интерфейсы SimpleMapItem и MapMode соответственно. В SimpleMapItem есть параметр size, который отвечает за размер прямоугольника в treemap, ему будем присваивать количество заработанных депутатом денег.
Читаем данные и сохраняем их в объекте DeputatItem, который реализует интерфейс SimpleMapItem. Созданный объект с информацией о депутате добавляем в объект DeputatMap (реализация интерфейса MapModel).
DeputatMap dMap = new DeputatMap();
String[] lines = loadStrings("parliamentV2010.csv");
for (int i = 0; i < lines.length; i++)
{
//... получаем id, party, name, money из lines[i]
DeputatItem d = new DeputatItem(id, party, name, money);
dMap.addDeputat(d);
}
dMap.finishAdd();
Создаем объект Treemap, отдавая ему в качестве параметров DeputatMap, и размеры прямоугольника, в котором строить диаграмму.
Treemap treemap = new Treemap(dMap , 0, 0, width - 1, height - 1);
//Меняем алгоритм на SquarifiedLayout и обновляем объект treemap
MapLayout algorithm = new SquarifiedLayout();
treemap.setLayout(algorithm);
treemap.updateLayout();
Предыдущий код выполняются в функции Processing'а setup(), а в функции Processing'а draw() вызываем функцию draw() объекта treemap.
void draw() {
treemap.draw();
}
Если каждому депутату задать цвет в соответствии с партией, к которой он принадлежит, и вывести информацию по депутатам в тех ячейках, размер которых это позволяет, то мы получим такую картинку:
![null](http://artprocessing.ru/wp-content/uploads/2012/01/DumaVFirstTry.png)
Я решил сгруппировать депутатов, принадлежащих к одной партии: для этого нужно добавить еще один уровень иерархии — партии. Схематично структуру дерева, полученную на предыдущем этапе, можно представить так: Дума->депутаты, добавив партии получим: Дума->партии->депутаты. Для такой схемы понадобятся еще два класса PartyItem (реализация интерфейса SimpleMapItem) и PartyMap (реализация интерфейса MapModel). После аналогичных шагов по созданию treemap получается такая картинка:
![null](http://artprocessing.ru/wp-content/uploads/2012/01/DumaV2010Money.png)
![null](http://artprocessing.ru/wp-content/uploads/2012/01/DumaVLegenda.png)
Картинки дают понять общую структуру распределения доходов, но найти конкретного депутата по картинке, к сожалению, не получится. Для этого можно воспользоваться интерактивной версией или скачать приложение для windows, linux, mac os, или запустить в процессинге, скачав исходный код.
P. S. Treemap можно строить не только в Processing'е. Natan Yu, автор блога Flowing data, пропагандирует такой подход к визуализации информации: работаем с данными в программе статистического анализа- R, полученное изображение потом доводим до ума в Иллюстраторе. Натан недавно выпустил книгу, в которой подробно описан такой подход. В R есть специальная функция для построения Treemap, для интересующихся сслылка на топик в блоге Натана.
Есть также JavaScript реализации:
Google Chart Tools Treemap;
d3.js Treemap;
JavaScript InfoVis Toolkit Treemap.