Визуализации, приводимые в этой статье основаны на идее Elana Levin и на ее статье, в которой рассказывается о формировании портретов при помощи бар-чартов (столбчатых диаграмм) в инструменте Datawrapper. Для работы с изображениями и данными используется Processing. Прямого перевода с английского для этого метода нет, поэтому будем называть это bar chart портреты.
В настоящей статье я буду использовать Python для получения датасета и Tableau для визуализации полученных данных.
Основная идея — построение изображений при помощи бар-чартов. Это нетривиальное использование диаграмм такого типа, и в задачах бизнеса такой способ не нужен, но такие задачи позволяют лучше понять инструмент Tableau и поработать с библиотекой pillow в Python.
1. Подготовка изображения
Для того, чтобы подготовить изображение для преобразования в данные, нужно взять исходное изображение и изменить его размеры в графическом редакторе так, чтобы количество пикселей по горизонтали и вертикали соответствовало количеству точек, которое вы хотите вывести на визуализации. Каждая точка будет соответствовать одному бару.
Я нашел фотографии актеров, у которых нет ни одного Oскара здесь
После этого выбрал 10 актеров и уменьшил фотографию каждого до 100×120 пикселей. Можно это сделать в paint. Возьмем фото Эдди Мёрфи и изменим размеры:
Сохраним файл в .png.
2. Преобразование фото в данные
Каждый бар на визуализации будет представлять один пиксель, а длина бара — яркость этого пикселя, поэтому нам нужно получить датасет с координатами всех пикселей и их яркостью. Для этого используем Python:
from PIL import Image
import numpy as np
import csv
import os
# open picture as greyscale pic, creating an array
img = np.array(Image.open("C:\\Docs\\Bar Portraits\\Murphy.png").convert('L'))
def csvWriter(fil_name, nparray):
example = nparray.tolist()
with open(fil_name+'.csv', 'w', newline='') as csvfile:
writer = csv.writer(csvfile, delimiter=',')
writer.writerows(example)
# write data to csv
csvWriter("C:\\Docs\\Bar Portraits\\Murphy_temp", img)
# numerate rows
with open("C:\\Docs\\Bar Portraits\\Murphy_temp.csv", 'r') as read_object, open("C:\\Docs\\Bar Portraits\\Murphy.csv", 'w') as write_object:
for idx, line in enumerate(read_object, start=1):
write_object.write('{}, {}'. format(idx, line))
# remove temp file
os.remove("C:\\Docs\\Bar Portraits\\Murphy_temp.csv")
Внимание: в коде замените путь до рабочего каталога на своей машине.
На выходе получим матрицу данных с пронумерованными строками:
В этой таблице значения в столбце А — номера строк, а значения в остальных столбцах — значения яркости. Максимальное значение — 255. Размер таблицы эквивалентен размеру картинки, и в нашем случае — 100×120. То есть, каждая ячейка таблицы содержит информацию о яркости соответствующего пикселя.
3. Рисуем портрет в Tableau
Подключив файл .csv к Tableau, получим следующую таблицу:
Делаем операцию pivot над всеми столбцами кроме первого:
Делаем операцию split для столбца Pivot Field Names, оставляем только столбец с числовыми значениями и переименовываем поля:
Всё! Данные готовы для визуализации.
Создаем поле Brightness_actual:
255 — [Brightness]
И строим портрет:
Портрет готов.
По факту сама визуализация — это таблица 100×120, в каждой ячейке которой находится один бар с длиной, эквивалентной яркости в этой точке.
Можно менять типы Marks, использовать цвета чтобы получать другие формы изображений. Например, если в marks выбрать circles и положить в цвет Brightness_actual, получим следующее:
Это наверное надо называть не bar chart портреты, а как-то по-другому.
Можно добавить больше фотографий в один датасет, используя Union и включить анимацию для трансформации фотографий. В примере ниже показано изменение позиции пикселей фотографий и их трансформация в пиксели других фото. Для этого используются дополнительные вычисления.
Здесь можно много экспериментировать, и результат вас порадует в любом случае.
Моя конечная визуализация позволяет настраивать яркость за счет увеличения и уменьшения длины бара, также есть возможность переключения на разные типы Marks.