Облако слов (Word Cloud) — это визуализация, содержащая слова из некоторого набора данных, при этом размер шрифта прямо пропорционален частотности слова в наборе. В качестве примера можно привести облако слов, основанное на словах романа Роберта Льюиса Стивенсона «Остров Сокровищ«. Здесь можно выделить наиболее часто встречающиеся слова в романе — они представлены шрифтом большего размера:

word cloud Python

Это облако слов получилось при помощи кода Python. Этот код и принцип его работы рассмотрим в статье. Всего я сделал 25 таких визуализаций по самым известным произведениям. Их можно найти на этом сайте в проекте «Книги». Кроме этого в статье рассмотрим как создавать кастомные облака слов в Tableau, предварительно рассчитав координаты слов в Python. Пример визуализации в Tableau, в которой представлены слова из названий величайших фильмах по их частотности:

custom word cloud Tableau
Click to open the interactive viz

Дополнительно про Word Clouds в Python можно прочитать в статьях:

  1. Genegating WordClouds in Python
  2. Word Cloud in Python

1. Подготовка данных

В Python есть библиотека WordCloud, которая позволяет создавать облака слов. Примеры таких визуализаций и код на Python есть в документации к этой библиотеке. Для работы с этой библиотекой надо подготовить данные. Датасет о Top 1000 величайших фильмов я взял с веб-страницы сайта theyshootpictures.com. Простого копирования в Excel и немного работы с разделениями столбцов достаточно для того чтобы данные выглядели так:

В коде ниже будут анализироваться только названия на английском языке поля Film.Остальные поля могут использоваться как дополнительная информация в визуализации. Этот файл был сохранен как 1000 Top Films.csv Для анализа литературных произведений проекта «Книги» я использовал обычные текстовые файлы c произведениями. Сами произведения доступны на открытом ресурсе gutenberg.org. То есть, получился список файлов с произведениями:

2. Облака слов в Python

Код ниже создает облако слов из названий 1000 величайших фильмов.

import pandas as pd
import numpy as np
import matplotlib.pylab as plt
from PIL import Image
from stop_words import get_stop_words
from nltk.corpus import stopwords
import time
from wordcloud import WordCloud, STOPWORDS, ImageColorGenerator, get_single_color_func

#read text
data2 = pd.read_csv ('C:/Docs/Tableau/Projects/Word Cloud/1000 Best Films/1000 Top Films.csv', usecols = ['Film'], sep = ',', encoding="ISO-8859-1")

start_time = time.time()

#read stoplist
stoplist = pd.read_csv ('C:/Docs/Tableau/Projects/Word Cloud/Books/Stop List.csv', usecols = ['Word'], sep = ',', encoding="utf-8")

print(data2)
print(stoplist)

df =pd.DataFrame (stoplist, columns=["Word"])
stop_list = df["Word"].tolist()

a1 =pd.DataFrame (data2)
a3 = pd.DataFrame.to_string(a1)
a0 = a3.upper()

stop = get_stop_words('en')
print (stop)
stop.extend(stop_list)
stop.extend(["thou", "thy", "thee", "dost", "les"])
stopwords = set(stop)

print(stopwords)

building = np.array(Image.open('C:/Docs/Tableau/Projects/Word Cloud/1000 Best Films/Video.jpg'))
wordcloud = WordCloud(max_words=50000,
stopwords = stopwords,
font_path='C:/Windows/Fonts/courbd.ttf',
prefer_horizontal=.7,
colormap='Blues',
min_font_size=5,
max_font_size=70,
background_color="Black",
width=7680,
height=4320,
margin=2,
collocations=False,
mask=building,
repeat=False,
relative_scaling=0,
scale=1,
min_word_length=3,
include_numbers = False,
normalize_plurals = False,
font_step=1).generate(a0)

print (wordcloud.layout_)

df = pd.DataFrame(wordcloud.layout_, columns = ['Name', 'Size', 'Coord', 'Direction','Color'])
df.to_csv('C:/Docs/Tableau/Projects/Word Cloud/1000 Best Films/Films_Coordinates.csv')

print(' ')
print ("time elapsed: {:.2f}s".format(time.time() - start_time))

plt.figure(figsize=(30,30))
plt.imshow(wordcloud)
plt.axis("off")
plt.tight_layout(pad=0)
plt.show()

Этот код читает текст из файла 1000 Top Films.csv, а также читает STOPLIST из другого файла .csv. В стоплисте содержатся слова, которые будут удаляться из исходного текста. Также можно использовать стоплисты из библиотек типа stop_words или nltk:

from stop_words import get_stop_words
from nltk.corpus import stopwords

Кроме этого в коде есть возможность ввода стоп-слов, это реализовано в строке, которая добавляет сова в список стоп-слов:

stop.extend(["thou", "thy", "thee", "dost", "les"])

Следующая строка читает файл маски:

building = np.array(Image.open('C:/Docs/Tableau/Projects/Word Cloud/1000 Best Films/Video.jpg'))

В результате выполнения кода получается такое облако слов:

word cloud Python

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

max_words=50000 Максимальное количество слов в облаке = 50000
font_path=’C:/Windows/Fonts/courbd.ttf’ Выбор шрифта
prefer_horizontal=.7 Ориентация слов. 70% слов будут располагаться горизонтально
colormap=’Blues Цветовая гамма
min_font_size=5 Минимальный размер шрифта
max_font_size=70 Максимальный размер шрифта
background_color=»Black» Цвет фона
width=7680, height=4320, Разрешение картинки 
margin=2 Ширина границы между словами
collocations=False Использование словосочетаний. Отключено
mask=building Маска использует файл .jpg с кинокамерой
repeat=False Повторение слов в облаке. Отключено
relative_scaling=0 Масштабирование слов точно по количеству их повторений. Отключено.
scale=1 Масштабирование картинки. Не масштабируется
min_word_length=3 Минимальное количество букв в слове
include_numbers = False Использовать числительные. Отключено
normalize_plurals = False Нормализация множественного числа (убирает букву s в конце английских слов). Отключено
font_step=1 Шаг шрифта

Это не все параметры, которые можно использовать. Все параметры и их описание можно найти в описании библиотеки WordCloud.

Важно: библиотека wordcloud не со всеми шрифтами работает корректно, поэтому сначала лучше проверить на небольшом объеме данных как отображается выбранный вами шрифт

Следующие строки в коде нужны для расчета времени выполнения кода и вывода времени на экран, они не влияют на саму визуализацию:

import time

start_time = time.time()

print ("time elapsed: {:.2f}s".format(time.time() - start_time))

Также после выполнения кода будет сгенерирован файл Film_Coordinates.csv, в котором будут перечислены пары координат X и Y для каждого слова. Этот файл нужен только для того, чтобы перенести облако слов в Tableau.

Все буквы приводим к верхнему регистру в строке:

a0 = a3.upper()

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

3. Стоп-слова

Стоп-слова — это слова, которые мы не хотим видеть в облаке слов, поэтому отбрасываем их.

В коде используется библиотека stop_words, в которой список стоп-слов на английском выглядит так:

['a', 'about', 'above', 'after', 'again', 'against', 'all', 'am', 'an', 'and', 'any', 'are', "aren't", 'as', 'at', 'be', 'because', 'been', 'before', 'being', 'below', 'between', 'both', 'but', 'by', "can't", 'cannot', 'could', "couldn't", 'did', "didn't", 'do', 'does', "doesn't", 'doing', "don't", 'down', 'during', 'each', 'few', 'for', 'from', 'further', 'had', "hadn't", 'has', "hasn't", 'have', "haven't", 'having', 'he', "he'd", "he'll", "he's", 'her', 'here', "here's", 'hers', 'herself', 'him', 'himself', 'his', 'how', "how's", 'i', "i'd", "i'll", "i'm", "i've", 'if', 'in', 'into', 'is', "isn't", 'it', "it's", 'its', 'itself', "let's", 'me', 'more', 'most', "mustn't", 'my', 'myself', 'no', 'nor', 'not', 'of', 'off', 'on', 'once', 'only', 'or', 'other', 'ought', 'our', 'ours', 'ourselves', 'out', 'over', 'own', 'same', "shan't", 'she', "she'd", "she'll", "she's", 'should', "shouldn't", 'so', 'some', 'such', 'than', 'that', "that's", 'the', 'their', 'theirs', 'them', 'themselves', 'then', 'there', "there's", 'these', 'they', "they'd", "they'll", "they're", "they've", 'this', 'those', 'through', 'to', 'too', 'under', 'until', 'up', 'very', 'was', "wasn't", 'we', "we'd", "we'll", "we're", "we've", 'were', "weren't", 'what', "what's", 'when', "when's", 'where', "where's", 'which', 'while', 'who', "who's", 'whom', 'why', "why's", 'with', "won't", 'would', "wouldn't", 'you', "you'd", "you'll", "you're", "you've", 'your', 'yours', 'yourself', 'yourselves']

При анализе текстов книг мне не хватило этого списка, поэтому я создал отдельный файл Stop List.csv с наречиями, числительными, местоимениями, междометиями, числительными, предлогами, устаревшими и нецензурными словами. В списке оказалось больше 1000 слов, часть списка выглядит так:

Обратите внимание, что я добавил в стоп-лист слово Chapter (глава), поскольку для книг с небольшими главами это слово было очень частотным, но на сюжет книг оно не влияет.

Кроме этого, для каждого источника текста могут встречаться специфические слова, например, у Шекспира. Их можно убирать прямо в коде, добавляя в список:

stop.extend(["thou", "thy", "thee", "dost", "thus", "going",
"doth", "many", "much", "nay", "aye", "don", "isn", "ain",
"didn", "tis", "vii", "viii", "les"])

Таким образом, в качестве источника стоп-слов можно использовать:

  1. Библиотеки
  2. Файлы
  3. Список внутри кода

Также все эти списки можно объединять.

Таким образом мы избавляемся от частотных слов: предлогов, наречий, местоимений и пр., которые не характеризуют сюжет книги или смысл другого источника текста

4. Облака слов в Tableau

Стандартное облако в Tableau выглядит следующим образом:

word cloud

Это облако построена на частотности слов в книге «Алиса в стране чудес». Для его создания нужен датасет с каждым словом и частотностью его повторения в книге. Само Tableau не может создать такой датасет из текста книги, поэтому применяются сторонние инcтрументы, например, Python.

Такой тип визуализации подходит для небольших объёмов текстовых данных. Кроме того у этого облака слов есть существенные ограничения:

  1. Максимальный размер текста ограничен
  2. Слова можно располагать либо горизонтально либо вертикально
  3. Нельзя выбрать форму облака

В Python же таких ограничений нет. Кроме того, есть множество дополнительных настроек. Tableau же предоставляет дополнительные интерактивные возможности (фильтрация, actions). Поэтому можно рассчитать координаты слов в Python и потом перенести из в Tableau для создания кастомного облака слов.

Библиотека WordCloud позволяет забирать координаты слов, цвет и направление текста. Это делает метод wordcloud.layout_ в строках:

df = pd.DataFrame(wordcloud.layout_, columns = ['Name', 'Size', 'Coord', 'Direction','Color'])
df.to_csv('C:/Docs/Tableau/Projects/Word Cloud/1000 Best Films/Films_Coordinates.csv')

Файл Film_Coordinates.csv выгладит так:

Его можно либо допилить в питоне (разделить X и Y, перевести цвета в шестнадцатеричный формат и т.д), либо перенести вычисления в Tableau. Пойдём вторым путем и сначала разделим поле Name и координаты при помощи SPLIT:

Name

TRIM( SPLIT( SPLIT( [Name], «(«, 2 ), «‘», 2 ) )

X

INT(TRIM( SPLIT( SPLIT( SPLIT( [Coord], «(«, 2 ), «,», 2 ), «)», 1 ) ))

Y

INT(TRIM( SPLIT( SPLIT( [Coord], «(«, 2 ), «,», 1 ) ))

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

INT(REGEXP_EXTRACT_NTH([Coord], ‘(\d+)’, 1))

Спасибо Артему Прыткову за совет по регулярным выражениям.

Если хотите больше знать о том как работать с текстом в Tableau при помощи регулярных выражений, можете почитать статьи:

  1. An Introduction To Tableau Regular Expressions (REGEX)’ by Ken Flerlage 
  2. Detailed Guide to Regular Expressions‘ by Rajeev Pandey

После этого построим точки начала координат на диаграмме разброса, используя картинку облака слов, полученное в Python, в качестве подложки:

word cloud

Можно видеть, что Python передал координаты верхних левых углов каждого слова. Tableau же работает с центрами (центроидами) слов. То есть, если представить каждое слово в виде прямоугольника, мы имеем координаты левых верхних углов, а нам нужны геометрические координаты центров этих прямоугольников. Поэтому нам нужно рассчитать координаты центров.

Кроме этого, в наших данных есть два направления слов: горизонтальное и вертикальное. Они задаются в поле Direction. Значение 2 — вертикальное направление, пустая ячейка — горизонтальное направление. В Tableau будем использовать Dual Axis где по одной оси будем отражать только горизонтальные названия, а по другой — только вертикальные.

Вычисления для координат центров прямоугольников (слов).

X Shift

IF ISNULL([Direction]) THEN
[X]+ [Parameter 1]*[Size]/2* LEN([Name Split])

ELSE [X]+ [Parameter 1]*[Size]/2
END

Y Shift Horizontal

IF ISNULL([Direction]) THEN
[Y][Parameter 1]*[Size]/2
END

Y Shift Vertical

IF ISNULL([Direction])=False THEN
[Y][Parameter 1]*[Size]/2* LEN([Name Split])
END

Эти вычисления основаны на делении длины и высоты слов пополам так чтобы координаты сместились от углов к центрам слов.

Важно: в визуализации используется моноширинный шрифт Courier New у которого ширина всех букв одинакова. Так центры прямоугольников точнее находятся в Tableau

Parameter 1 здесь нужен для подгонки слов. Это связано с тем что на разных разрешениях Tableau не меняет размер шрифта, поэтому приходится настраивать размер шрифта на панели Marks в Size. Параметром же дополнительно можно минимизировать зазоры между словами.

Поле Size в датасете — это размер шрифта, а Tableau использует площадь прямоугольника, в котором находится слово, поэтому в Size появляется квадрат: 

([Size]/2)^2

В итоге получится такая визуализация с двумя осями:

word cloud

На оси для вертикальных слов можно выбирать направление снизу вверх или сверху вниз в настройках направления текста.

Также надо настроить одинаковые шаги сетки по X и Y. Получим финальный виз:

word cloud Tableau
Click to open the interactive viz

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

В Color можно добавлять различные вычисления, например, если добавить X Shift то для фильмов получим такую картину:

word cloud Tableau

Заключение

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

Довольно интересно такие облака слов смотрятся в виде лого. Снизу примеры визуализаций, где анализировались сообщения в русскоязычных Telegram чатах Tableau (первая строка) и инфографики (вторая строка). Первый столбец — визы без стоп-слов, второй и третий — с отбросом стоп-слов.

word cloud