- PVSM.RU - https://www.pvsm.ru -
Чаще всего в работе датасаентиста мне приходится перегонять данные из одного представления в другое, агрегировать, приводить к одинаковой гранулярности и чистить данные, загружать, выгружать, анализировать, форматировать и присылать результаты (которые в общем-то тоже данные в каком-то виде). С данными всегда что-то не так и их нужно шустро гонять туда и обратно — больше всего в этом мне помогают классические юниксовые утилиты и небольшие, но гордые тулзы: вот о них-то мы сегодня и поговорим.
И сегодня будет подборка с примерами и ситуациями, в которых мне приходится их использовать. Все описанное здесь и ниже — это настоящий субъективный опыт и конечно же он у всех разный, но возможно кому-то он будет полезен.
Tools — learn the tools — все написанное субъективно и основано исключительно на личном опыте: помогло мне может быть поможет и вам.
Перед тем как вы начнете читать, напоминаем, что сейчас идет наша игра для кулхацкеров [1], в которой можно успеть выиграть деньги...
Как сейчас помню, мне было 17 лет и я установил линукс. Терминал и Баш. И как-то всегда баш был частью процесса и олицетворял для меня собственно работу в терминале. Спустя 12 лет после окончания PhD я попал в компанию, где был вводный документ и мне впервые в руки попался мак и я решил ему следовать.
И о чудо! Удобный переход по папкам, человеческое автодополнение, индикатор git, темы, плагины, поддержка виртуальной среды для python и тд — сижу теперь в терминале и не нарадуюсь!
Ставим zsh, как вы обычно ставите все и переходим к oh-my-zsh (по сути — это народная сборка рецептов, которые работают из коробки и добавили поддержку плагинов, тем и тд). Взять можно тут [2]. А также можно поставить тему [3] (ну например). Вот тут [4] неплохое демо возможностей. Взято из вот этой [5] статьи.
Одна из самых прекрасных конструкций терминала — это pipeline. Упрощенно говоря, он позволяет соединять выходы одной команды с входами другой, пример простого применения, который буквально взят из одной задачи, которой я занимался два дня назад.
Нужно было смоделировать задачу на одном языке для решения комбинаторных задач, запускалось все из терминала и выдавалось в абсолютно нечитаемом виде из текста, поставив простой значок | — соединили входы выходы и сделали поддержку форматирования:
| python.py format.py
Более интересная и каждодневная задача — оценить какой-нибудь параметр или характеристику по отгруженным данным, как правило — это ряд быстрых проверок, что нужные величины где-то на сервере с данными ведут себя хорошо — например мы хотим понять, что у нас с парсером и смотрим сколько во всех json файлах собрано уникальных групп — этот параметр должен естественно адекватно расти во времени:
cat data/*groups* | jq .group | uniq | wc -l
Мы подробнее поговорим о каждом из них, но общая идея уже понятна:
И сейчас мы подробнее посмотрим на wc.
wc — умеет быстро считать слова, строчки, буквы, байты и максимальную длину строчки, и все с помощью простых ключей:
—bytes
—chars
—words
—lines
—max-line-length
Кажется, что это тривиально, но оказывается невероятно часто нужно и удобно.
Повседневное использование, быстро оценим сколько у нас каких данных собрано (тут одна строка одна запись):
Подробнее тут [6].
Про них написаны тысячи мануалов и статей, но не могу не упомянуть — выдирают текст регулярками и своим языком запросов по соответствию образцу. В целом мне кажется ack более дружелюбным и простым в использовании из коробки, поэтому будет он тут:
Пример: быстренько находим вхождение слова (ключ “-w”) ga2m (тип модели), без учета регистра (ключ -i) в файлах исходниках питона:
Документация [7].
JQ — это прямо-таки grep/ack для json (хотя и с оттенком sed и awk — о последнем далее) — по сути простой парсер json и json line в командной строке, но иногда бывает чрезвычайно удобным — как-то пришлось парсить архив wikidata в формате bz2 он весит порядка 100ГБ и где-то 0.5TB uncompressed.
Из него нужно было выдрать соответствие между несколькими полями, что получилось сделать очень просто на машине практически без нагрузки на CPU и память, вот собственно та самая команда, которую я использовал:
bzcat data/latest-all.json.bz2 | jq —stream 'select((.[0][1] == "sitelinks" and (.[0][2]=="enwiki" or .[0][2] =="ruwiki") and .[0][3] =="title") or .[0][1] == "id")' | python3 scripts/post_process.py "output.csv"
Это был по сути весь пайплайн, который создавал нужный mapping, как мы видим все работало в режиме потока:
Итого сложный пайплайн работающий в режиме потока на больших данных (0.5TB), без существенных ресурсов и сделан из простого пайплайна и пары тулзов. Определенно рекомендую глянуть на досуге.
Удобнейшая вещь (особенно внутри вима): быстро ищет по файлам, что удобно на большом проекте — особенно, когда их у вас несколько. Как правило нужно для быстрого поиска файлов по определенному слову в большом проекте: у меня происходило погружение в новый проект, в который входит несколько крупных репозиториев и в качестве вводного задания мне нужно было добавить одну простую модель в ассортимент доступных в системе и мне нужно было быстро находить свои файлы по ключевому слову ga2m и работать по аналогии с другими «блоками кода» — быстро редактировать то одно, то другое — тут fzf очень хорошо приходит на помощь:
Ссылка на репозиторий [8].
Название происходит от первых букв создателей Aho, Weinberger и Kernighan: по сути скриптовый язык обработки текстово-табличных данных — он приминяет шаблоны трансформации к каждой строке файла
Как правило идеально подходит для быстрых разовых трансформаций, например, у нас были собранный руками датасет в виде tsv, а процессор принимал на вход jsonl причем ожидал доп поле “theme”, которого не было в исходном файле (нужного для некоторых вещей, которые были не критичны для текущих подсчетов) — итого, был написан простой однострочник:
cat groups.tsv | awk '{ printf "{"group": "%s", "theme": "manual" }n", $1 }' > group.jsonl
По сути он брал файлик и каждую строчку заворачивал json с нужными полями.
Ссылка с tutorial [9].
Регулярно скрипты и пайплайн должны что-то откуда-то подтянуть и качнуть — и wget не подводит: умеет докачивать, авторизовываться, proxies, cookies да еще и помимо http(s) умеет в ftp.
Швейцарский нож [10] в скачивании.
Сommand history: hstr [11]
Регулярно мне приходится искать что-то в истории команд:
Поэтому мне довольно критично иметь хороший и удобный поиск по истории команд, пока hstr полностью со своей задачей справляется:
В финале я бы упомянул полезными — но тянущими на отдельную статью темы — полезно глянуть:
Автор: oldadmin
Источник [12]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/data-mining/355926
Ссылки в тексте:
[1] игра для кулхацкеров: https://habr.com/ru/company/ruvds/blog/514776/
[2] тут: https://github.com/ohmyzsh/ohmyzsh
[3] тему: https://github.com/romkatv/powerlevel10k
[4] тут: https://vimeo.com/249268080
[5] этой: https://medium.com/@ivanaugustobd/your-terminal-can-be-much-much-more-productive-5256424658e8
[6] тут: https://ss64.com/bash/wc.html
[7] Документация: https://stedolan.github.io/jq/
[8] репозиторий: https://github.com/junegunn/fzf
[9] tutorial: https://www.geeksforgeeks.org/awk-command-unixlinux-examples/
[10] Швейцарский нож: https://www.gnu.org/software/wget/
[11] hstr: https://github.com/dvorka/hstr
[12] Источник: https://habr.com/ru/post/514990/?utm_source=habrahabr&utm_medium=rss&utm_campaign=514990
Нажмите здесь для печати.