[Перевод] Эти прекрасные древовидные карты (альтернатива pprint)
Древовидные карты — это инструмент визуализации, позволяющий обобщать данные разной формы и размеров. На сегодня они чаще всего используются для отображения файлов, занимающих всё пространство диска, но путём некоторых доработок их можно сделать гибким инструментом для анализа и навигации по беспорядочным массивам данных.
Древовидные карты заполняют всё пространство. Вы указываете границы, и алгоритм генерирует график, занимающий все пиксели обозначенной области. Это отличает их от модуля pprint
, который генерирует представление данных, пропорциональное их количеству. Возможность ограничения визуальной области даёт преимущество в том, что древовидные карты изящно масштабируются для данных небольшого и среднего размеров.
Такие карты задействуют для представления данных все доступные пиксели. Как правило, чем больше пикселей, тем более чётким получается представление. Тем не менее древовидная карта отлично подходит и для относительно небольших размеров.
Причём этот алгоритм очень гибок. Он способен визуализировать любые древовидные данные, которые можно представить в виде JSON или edn.
Что такое древовидные карты?
Древовидное картирование — это метод отображения иерархических данных с помощью вложенных фигур, обычно прямоугольников (Wikipedia).
По своей сути построение древовидной карты происходит просто. Алгоритму предоставляются древовидные дынные, он делит их прямоугольник на более мелкие прямоугольники для каждой из ветвей, а затем рекурсивно проделывает те же действия для каждой ветви.
(defn treemap [tree-node rect]
(if (branch? tree-node)
(let [child-rects (subdivide rect (children tree-node))]
(mapcat (fn [child child-rect]
(treemap child child-rect))
(children tree-node)
child-rects))
[rect]))
Размер каждого прямоугольника пропорционален размеру связанного с ним узла дерева и всех его потомков. Чем больше потомков у узла, тем больше прямоугольник. В качестве дополнения функцию, которая определяет размер листьев и веток, можно параметризовать, но для наших примеров мы предположим, что все листья имеют размер 1, а размер ветви равен сумме её листьев.
Вот как выглядит описанный процесс деления:
Здесь мы видим, что простая древовидная карта показывает лишь часть структуры визуализируемых данных, и многие элементы в этом базовом представлении не отображаются. Далее мы рассмотрим ряд приёмов для улучшения древовидных карт, позволяющих показывать больше элементов структуры данных. Здесь я опишу далеко не полный список всех доступных техник. По факту вам доступно огромное пространство для экспериментов и доработок.
Улучшение стандартной древовидной карты
Древовидные карты хороши тем, что используют все доступные пиксели, но нужно подумать, как лучше эти пиксели использовать. Есть несколько метрик и аспектов данных, которые можно визуализировать. Разберём некоторые.
- типы: какие типы используются в данных?
- форма: какие у нас данные (глубокие, неглубокие, тонкие, широкие)?
- кардинальность: сколько у нас данных?
- ограничения: какие свойства должны иметь данные, чтобы считаться допустимыми?
▍ Типы
Одно из наиболее очевидных улучшений подразумевает закрашивание фона каждого прямоугольника согласно типу представляемых им данных. Выглядеть это будет так:
Отлично! Теперь мы видим присутствующие в дереве типы. Тем не менее в нашем плане есть недочёт. Дело в том, что в большинстве файлов JSON данные состоят преимущественно из строк и чисел. Нас же в случае обобщения интересуют типы данных более высокого уровня, что может быть вызвано отсутствием подходящей схемы. Здесь можно подумать об автоматическом приведении типов, но пока давайте разберём другие аспекты.
▍ Глубина
Одна из проблем с выделением только типов в том, что они ничего не сообщают нам о фактической структуре данных. На основе одних только типов мы не можем понять, насколько они глубоки или широки. Если мы не станем использовать цвет для представления типов, то с помощью него можно выразить глубину:
Применение цвета для отражения глубины конкретно покажет, насколько широки или глубоки данные, но в этом случае по-прежнему будет трудно понять их структуру. Например, какие прямоугольники имеют одного родителя?
▍ Группировка
Показать, какие прямоугольники принадлежат одному родителю, можно путём добавления на каждый уровень отступов.
Превосходно. Небольшие разрывы помогут отличить разные ветви дерева и понять, какие элементы относятся к одному родителю. Тем не менее, если мы отражаем группы элементов только с помощью отступов, то сталкиваемся с ограничением. Какой отступ должен присутствовать на каждом уровне иерархии? Излишне малый сделает разделение менее очевидным. Слишком большой приведёт к трате дополнительных пикселей, которые можно было бы задействовать более эффективно. На объём желательных отступов также повлияет форма данных. Размер отступов, удачно подходящий для различных типов данных, нужно продумать дополнительно.
▍ Линии иерархии
Ещё один способ визуализировать форму данных — это просто нарисовать линии от родителей к потомкам. Можно даже изменять цвет линии, демонстрируя, к какому типу каждая коллекция относится.
Основной недостаток линий иерархии в том, что они могут накладываться и нарушать чёткость прямоугольников потомков. Можно частично устранить эту проблему, увеличив прозрачность линий в верхней части дерева. Однако для определённых форм данных они всё равно будут проблемой. В качестве дополнительного способа сделать график более чистым, сохранив линии иерархии, можно реализовать возможность наведения на него курсора, чтобы показывать линию только того элемента, на который он наведён.
Ниже представлена та же визуализация данных, что и выше, но здесь фоновый цвет показывает глубину, а линии иерархии отображаются только при наведении курсора на различные элементы.
▍ Метки
В простых случаях можно просто размечать все данные.
{:a [0 1 2 3 4],
:b [0 1 2 3 4],
:c [0 1 2 3 4]}
▍ Разметка ключевых путей
Одной из типичных форм вложения являются карты, содержащие другие карты. Мы можем привлекать внимание к важным структурным особенностям данных, выделяя ключевые пути.
Ниже приводится древовидная карта всех public intern
в пространствах имён, указанных в параметре classpath
и начинающихся с clojure.*
.
Дополнительно помогая пользователю, мы позволяем ему наводить курсор на данные и показываем ключевой путь, который нужно проделать, чтобы попасть в этот листовой узел.
Помимо помощи в определении местонахождения данных, ключевой путь также может использоваться как часть самого UI. Пронаблюдайте, как при наведении курсора на графике карты выделяется область соответствующего подраздела.
Сравнение с альтернативами
Существует несколько инструментов, которые помогают выработать интуицию относительно конкретного представления данных. Давайте сравним древовидные карты с другими вариантами, чтобы понять, как их можно наиболее эффективно использовать в составе набора инструментов для анализа данных.
▍ Древовидные карты
Древовидные карты прекрасно отражают высокоуровневую структуру, если она является иерархической, гетерогенной и приблизительно квадратной (когда количество слоёв данных в ширину и глубину почти одинаковое). Проблемными же для них являются данные, которые либо широкие и неглубокие, либо тонкие и глубокие.
▍ pprint
pprint отлично работает для данных от малого до среднего размера, особенно когда они вписываются в одну страницу. Если же данные занимают более одной страницы, форма и чёткость структуры начинают страдать.
▍ Браузеры данных
Браузеры данных вроде rebl хорошо подходят для сканирования данных, но обычно показывают только один их уровень одновременно. Многие браузеры позволяют встраивать графику, поэтому, надеюсь, что древовидные карты будут интегрированы в один из таких инструментов, что позволит видеть более обширную картину обобщения данных.
▍ Схемы
Схемы нацелены на предоставление абстрактных сводок. Они плохо работают с вложенными данными, данными, которые не синхронизированы со схемой, и данными, у которых схемы нет. Схемы зачастую содержат свойства, которые больше не используются или выработали иное значение, отличное от того, которое предполагает их исходное название. При этом они по-прежнему очень полезны и могут дополнять инструменты, работающие с конкретными экземплярами данных, такие как древовидные карты, pprint
и браузеры данных.
Дальнейшая работа
▍ Усложнение композиции
Компоновка древовидных карт в treemap-clj
откровенно примитивна. Она учитывает всего один уровень одновременно и использует только простую эвристику, предпочитая близкие к квадрату прямоугольники более вытянутым и тонким.
Сейчас композиция прямоугольников выполняется лишь для одного уровня одновременно. Желательно же иметь возможность создавать более качественные представления, включающие более одного уровня дерева.
▍ Непрямоугольные древовидные карты
Во всех композициях treemap-clj
прямоугольники разделяются на более мелкие прямоугольники. Тем не менее в литературе описываются алгоритмы, способные делить области на другие фигуры, которые могут иметь интересные варианты применения.
▍ Интерактивное отображение глубины
Предоставление пользователю возможности интерактивно отрисовывать древовидную карту вплоть до глубины Х уровня наверняка станет полезным дополнением при анализе структуры данных.
▍ Альтернативные цветовые схемы
В treemap-clj
цветом можно отражать только два аспекта данных — глубину и тип. Желательно реализовать и другие цветовые схемы.
▍ Альтернативные функции определения размера
Как говорилось выше, во всех реализациях treemap-clj
используется размер узла, равный 1. Подстановка других функций вычисления размера позволит пользователю выделять различные элементы структуры данных.
▍ Использовать в композиции направление для отражения дополнительной информации
Если взглянуть на другие графики визуализаций, то направления в них обычно отражают некую информацию (например, движение финансового графика вверх и вправо обычно является хорошим признаком). Сейчас направления в древовидной карте не несут никакого значения. Нужно добавить функциональность размещения прямоугольников с определёнными свойствами близко к краям или к центру для выделения различных качеств данных.
▍ Графический дизайн
Я плохо знаком с графическим дизайном и наверняка нарушил множество его принципов. Более профессиональный подход к дизайну должен значительно повысить ясность и различимость содержимого карт.
▍ Ограничения, схемы и спецификации
Формальные спецификации данных содержат множество информации. Внедрение этих спецификаций в график древовидной карты повысит его информационную плотность.
▍ Приближение и отдаление
По аналогии с географическими картами, в древовидных должна быть возможность приближать интересующие области для более детального рассмотрения или, наоборот, отдалять представление для обзора более высокоуровневых особенностей.
Telegram-канал с розыгрышами призов, новостями IT и постами о ретроиграх