Визуализации, приводимые в этой статье основаны на идее Elana Levin и на ее статье, в которой рассказывается о формировании портретов при помощи бар-чартов (столбчатых диаграмм) в инструменте Datawrapper. Для работы с изображениями и данными используется Processing.

В настоящей статье я буду использовать 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, получим следующее:

Можно добавить больше фотографий в один датасет, используя Union и включить анимацию для трансформации фотографий. В примере ниже показано изменение позиции пикселей фотографий и их трансформация в пиксели других фото. Для этого используются дополнительные вычисления.

Здесь можно много экспериментировать, и результат вас порадует в любом случае.

Моя конечная визуализация позволяет настраивать яркость за счет увеличения и уменьшения длины бара, также есть возможность переключения на разные типы MarksL

Клик для перехода