- PVSM.RU - https://www.pvsm.ru -

Как-то, решая проблему лингвистического анализа в Power BI и заодно подыскивая примеры для моей предыдущей статьи [1], я вспомнил о задаче, которую пытался решить в Excel ещё несколько лет назад: нужно было внедрить в аналитическую систему словарь русского языка для лингвистического анализа большого количества запросов на естественном языке. Причём желательно было использовать стандартные офисные инструменты. Подавляющее большинство людей сразу взялись бы решать эту задачу в Excel, и я когда-то пошёл по тому же пути. В качестве словаря использовал открытый корпус русского языка (http://opencorpora.org/ [2]).
Но меня ждало разочарование — словарь состоял из 300 тыс. словоформ, более 5 млн записей, а для Excel это в принципе невозможный объём. Даже если запихнуть в него «всего лишь» 1 млн строк, то выполнять с ними какие-то манипуляции или, упаси боже, вычисления, сможет только очень терпеливый человек, который вообще никогда и никуда не торопится. Но в этот раз я решил натравить на задачу более подходящий инструмент — Power BI.
Я считаю этот продукт во многом недооценённым профессиональным сообществом. Power BI — это набор инструментов бизнес-анализа, который создавался для пользователей, владеющих Excel на чуть более высоком уровне, чем «подбить сумму по колонкам». Если человек способен написать в Excel формулы средней сложности, то освоит Power BI за пару вечеров.
Это не единый продукт с какой-то внутренней программистской логикой, а система из трёх компонентов:

Кривая обучения на первом этапе очень резко возрастает: если вы неплохо владеете Excel, то 80 % возможностей Power BI раскроются вам после короткого изучения. Это очень мощный инструмент, довольно лёгкий в использовании, но — до определённого момента. Чтобы задействовать его на полную мощность, вам уже потребуются опыт и глубокое знание языков М и DAX.
Кому он может быть полезен? В первую очередь, любым бизнес-пользователям, которым приходится обрабатывать и анализировать довольно крупные объёмы данных, когда Excel уже не справляется или пыхтит на пределе возможностей. Подчеркну — Power BI Desktop предназначен для широкого круга пользователей, решающих очень разнообразный спектр задач. К примеру, в моём случае речь шла о нормализации 5 млн текстовых записей для последующего определения частотности ключевых слов.
Это востребовано при обработке анкет, запросов поисковых систем, рекламных объявлений, диктантов/сочинений, каких-то статистических массивов и т. д. Или для разгадывания кроссвордов…
Ещё один кейс и вариант реализации рассмотрен в статье [3] о «распознавателе» Дмитрия Тумайкина. Реализовано на классическом Excel, но с использованием макросов…
Другой популярный сценарий подобного применения Power BI — вычисление соотношения показателей за текущий и предыдущий период. Например, у нас есть предагрегированные данные по выручке, и нужно сравнить её по дням с предыдущим кварталом, или годом, или аналогичным периодом. Причём хочется/требуется вставить результат сравнения в соседнюю колонку в виде значений, а не формул. Казалось бы, для Excel простейшая задача, написать простую формулу сравнения и протянуть по всем ячейкам колонки. Но только не в том случае, если у вас несколько миллионов строк в таблице. В самом DAX эта задача решается даже проще, чем в Excel, но тоже только с помощью поствычислений.
Можно привести ещё множество других практических сценариев применения Power BI, но суть вы, я думаю, уже поняли. Конечно, все эти задачи не проблема для программиста, владеющего, например, Python или R, но таких специалистов априори на порядки меньше, чем знатоков Excel. Вот только у Excel возможности ограничены, чего не скажешь о Power BI, который использует формульный язык DAX, очень похожий на формульный язык Excel, и способен налету обрабатывать миллионы и десятки миллионов записей. А дальше уже нужно наращивать оперативную память (хоть до 100, хоть до 300 Гб).
Но вернёмся к моей задаче. Нужно было придумать, как нулевой линии техподдержки автоматически оценивать тематику обращений пользователей. Для начала я решил вычленять определенные словоформы и по частоте их появления в обращениях определять самые важные темы, которые пользователи поднимают чаще всего.
Исходный словарь — это простой текстовый файл, который имеет регулярную структуру и выглядит так:

Для статистических целей нужно было для каждой словоформы определить начальную форму: для существительных — единственное число именительного падежа, для глаголов — неопределённую форму и т.д. Для программистов эта задача была проще простого: для каждого слова в левой колонке найти соответствие той форме, которая стоит сразу за номером этого слова в словаре.
Вот только среднестатистический бизнес-пользователь, не владеющий Python, специализированными инструментами и навыками разработки, не сможет решить эту задачу без использования self-analytics BI или подобного user-friendly инструментария. Причём, если данные нужно обработать для своих внутренних нужд или в них нет конфиденциальной информации, требующей защиты, то Power BI в этом случае будет ещё и бесплатен*.
Чтобы проанализировать данные, мне нужно было в Power Query, в таблице из 5 млн записей, добавить новый столбец, смещённый на одну позицию. Сначала я попытался применить ставший классическим подход с использованием Power Query, который описан [4] на портале сообщества Power BI Марселем Бюгом (Marcel Beug), автором оригинального интерактивного справочника по Power Query (написанного тоже на Power Query). В статье предлагается два разных алгоритма: один навеян идеями Мэтта Элингтона —известного гуру и тренера по Power BI, а второй подход — оригинальная идея самого Марселя, с использованием дополнительной функции. Несмотря на то, что для увеличения производительности я полностью кэшировал исходные данные, оба подхода потребовали гигантского количества времени — уже пошли восьмые сутки, а процесс так и не завершился. Размер исходного файла был 270 Мб, а текущий размер обработанных данных подобрался к 17 Тб. Уверен, немногие пользователи Power BI видели такие числа в окне загрузки данных из файлового источника.

Почему так раздулся объём, непонятно; даже декартово произведение всех записей получается сильно меньше 16 Тб. Здесь внутренний оптимизатор оказался явно не на высоте. А, например, DAX-Studio не позволяет трейсить запросы Power Query, только DAX. Может быть, кто-то поделится своим опытом траблшутинга PQ?
Не дожидаясь завершения первого процесса, я решил на другой машине попробовать решить задачу с помощью DAX посредством самописного запроса. Запрос выполнился… примерно за 180 секунд, а потребление памяти возросло незначительно.

Исходный код запроса на DAX:
KeyWord =
CALCULATE(
TOPN(1;
CALCULATETABLE(
VALUES(ShiftedList[Word])
;ALLEXCEPT(ShiftedList;ShiftedList[Word Nr])
)
)//TOPN
)//CALCULATE
Т. е. для каждой строки в новом столбце [KeyWord] ищется самое первое значение столбца [Word], содержащего все варианты словоформ, имеющее такой же номер базовой словоформы (столбец [Word Nr]). Пока формат исходного файла будет оставаться неизменным, запрос должен отрабатывать без ошибок и на всех последующих релизах словаря.
Код запроса в Power Query, формирующего исходную таблицу в требуемом формате, был сформирован «на автомате» и выполнился менее чем за минуту:

После того, как за три минуты в PowerPivot-интерфейсе сформировался столбец ключевых слов, поиск любых словоформ в интерфейсе Power BI занимает не более 4 секунд. Причём контрольный поиск тех же данных в любимом Notepad++ x64 мог занимать и 20 секунд, и даже больше. Но это не камень в огород NPP — искать по всему массиву данных труднее (и дольше), чем по уже размеченным данным.
К слову сказать, приведённый выше DAX-запрос родился не с первого раза, и промежуточные варианты выедали всю доступную память, работали долго и завершались либо ошибкой данных, либо нерелевантным результатом.

В итоге размер сохранённого PBIX-файла стал меньше исходного текстового словаря на 60 % (112 Мб), но более чем в 4 раза превысил размер ZIP-архива с тем же самым словарём.
Возвращаясь к баттлу между Power Query и DAX: разница в длительности выполнения одной и той же операции в разных компонентах говорит о том, что Power BI — не лом, против которого нет приёма. У него свой характер и особенности применения, которые нужно учитывать в своей работе. Собственно, как и у любого инструмента. А к рекомендациям даже признанных гуру следует относиться с осторожностью.
Кажется, нобелевский лауреат Ричард Смолли говаривал, перефразируя первый закон Кларка: «Когда специалисты утверждают, что что-то осуществимо, то, вероятно, они правы (только не знают когда). Когда же они говорят, что это невозможно, то, скорее всего, они ошибаются».
Характеристики тестовой машины:
Процессор: Intel Core i7 4770@ 3,4 ГГц (4 ядра)
RAM: 16 ГБ
ОС: Windows 7 Корпоративная SP1 x64
Готовый словарь в формате Power BI можно скачать отсюда [5].
А здесь [6] доступна доработанная онлайн-версия словаря. Можете порешать с его помощью кроссворды на досуге :)

…Кстати, тогда, несколько лет назад, задача всё-таки была решена в Excel, хоть и не на 100 %. Просто для анализа текстов был использован не весь корпус русского языка, а частотный словарь. Для базовой очистки текста вполне подойдёт любой из top100 имеющихся здесь частотных списков [7] на несколько десятков килобайт.
Юрий Колмаков, эксперт Департамента систем консолидации и визуализации данных компании «Инфосистемы Джет» (McCow [8])
Автор: JetHabr
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/298440
Ссылки в тексте:
[1] предыдущей статьи: https://habr.com/post/422799/
[2] http://opencorpora.org/: http://opencorpora.org/
[3] статье: https://habr.com/company/realweb/blog/264591/
[4] описан: https://community.powerbi.com/t5/Desktop/Power-Query-previous-row-value-based-on-criteria-O/m-p/125837
[5] отсюда: https://cloud.mail.ru/public/L79E/N7Lgp9U5J
[6] здесь: https://app.powerbi.com/view?r=eyJrIjoiNjVkOWNlYmUtMTM4MC00ZDI0LWI2N2QtOGE0M2ZhZmRhMmUxIiwidCI6IjU4ZWY5MDU4LWUzYTQtNGZkNy1iOWZmLWQ2NGY4YzExMzEzMyIsImMiOjl9
[7] здесь частотных списков: http://opencorpora.org/?page=downloads
[8] McCow: https://habr.com/users/mccow/
[9] Источник: https://habr.com/post/429140/?utm_campaign=429140
Нажмите здесь для печати.