Хабрахабр

Заметки Дата Саентиста: маленькие утилиты — большая польза

Чаще всего в работе датасаентиста мне приходится перегонять данные из одного представления в другое, агрегировать, приводить к одинаковой гранулярности и чистить данные, загружать, выгружать, анализировать, форматировать и присылать результаты (которые в общем-то тоже данные в каком-то виде). С данными всегда что-то не так и их нужно шустро гонять туда и обратно — больше всего в этом мне помогают классические юниксовые утилиты и небольшие, но гордые тулзы: вот о них-то мы сегодня и поговорим.

И сегодня будет подборка с примерами и ситуациями, в которых мне приходится их использовать. Все описанное здесь и ниже — это настоящий субъективный опыт и конечно же он у всех разный, но возможно кому-то он будет полезен.

Tools — learn the tools — все написанное субъективно и основано исключительно на личном опыте: помогло мне может быть поможет и вам.

Перед тем как вы начнете читать, напоминаем, что сейчас идет наша игра для кулхацкеров, в которой можно успеть выиграть деньги...

Zsh и oh-my-zsh — после всех этих лет в Баше!

Как сейчас помню, мне было 17 лет и я установил линукс. Терминал и Баш. И как-то всегда баш был частью процесса и олицетворял для меня собственно работу в терминале. Спустя 12 лет после окончания PhD я попал в компанию, где был вводный документ и мне впервые в руки попался мак и я решил ему следовать.

И о чудо! Удобный переход по папкам, человеческое автодополнение, индикатор git, темы, плагины, поддержка виртуальной среды для python и тд — сижу теперь в терминале и не нарадуюсь!

Ставим zsh, как вы обычно ставите все и переходим к oh-my-zsh (по сути — это народная сборка рецептов, которые работают из коробки и добавили поддержку плагинов, тем и тд). Взять можно тут. А также можно поставить тему (ну например). Вот тут неплохое демо возможностей. Взято из вот этой статьи.

Pipelines

Одна из самых прекрасных конструкций терминала — это pipeline. Упрощенно говоря, он позволяет соединять выходы одной команды с входами другой, пример простого применения, который буквально взят из одной задачи, которой я занимался два дня назад.

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

| python.py format.py

Более интересная и каждодневная задача — оценить какой-нибудь параметр или характеристику по отгруженным данным, как правило — это ряд быстрых проверок, что нужные величины где-то на сервере с данными ведут себя хорошо — например мы хотим понять, что у нас с парсером и смотрим сколько во всех json файлах собрано уникальных групп — этот параметр должен естественно адекватно расти во времени:

cat data/*groups* | jq .group | uniq | wc -l

Мы подробнее поговорим о каждом из них, но общая идея уже понятна:

  • cat — (сокр. от concatenate) печатает содержимое файлов со словом «group» в названии из папки data/
  • jq — выдирает из json поле «group»
  • uniq — оставляет только уникальные группы
  • wc — с ключом -l считает строчки, т.е количество групп 

И сейчас мы подробнее посмотрим на wc.

WC — маленькая, но гордая утилитка для подсчета строк, слов и тд.

wc — умеет быстро считать слова, строчки, буквы, байты и максимальную длину строчки, и все с помощью простых ключей:

  • —bytes
  • —chars
  • —words
  • —lines
  • —max-line-length

     
Кажется, что это тривиально, но оказывается невероятно часто нужно и удобно.

Повседневное использование, быстро оценим сколько у нас каких данных собрано (тут одна строка одна запись):

Подробнее тут.

Ack/grep

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

Пример: быстренько находим вхождение слова (ключ “-w”) ga2m (тип модели), без учета регистра (ключ -i) в файлах исходниках питона:

JQ — парсим json в командной строке

Документация.

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, как мы видим все работало в режиме потока: 

  • bzcat читал часть архива и отдавал jq
  • jq с ключом —stream сразу выдавал результат и передавал его постпроцессору (так же как и с самым первым примером) на питоне
  • внутри постпроцессор — это простая машина состояний

Итого сложный пайплайн работающий в режиме потока на больших данных (0.5TB), без существенных ресурсов и сделан из простого пайплайна и пары тулзов. Определенно рекомендую глянуть на досуге.

fzf — fuzzy finder

Удобнейшая вещь (особенно внутри вима): быстро ищет по файлам, что удобно на большом проекте — особенно, когда их у вас несколько. Как правило нужно для быстрого поиска файлов по определенному слову в большом проекте: у меня происходило погружение в новый проект, в который входит несколько крупных репозиториев и в качестве вводного задания мне нужно было добавить одну простую модель в ассортимент доступных в системе и мне нужно было быстро находить свои файлы по ключевому слову ga2m и работать по аналогии с другими «блоками кода» — быстро редактировать то одно, то другое — тут fzf очень хорошо приходит на помощь:

Ссылка на репозиторий.

AWK

Название происходит от первых букв создателей Aho, Weinberger и Kernighan: по сути скриптовый язык обработки текстово-табличных данных — он приминяет шаблоны трансформации к каждой строке файла

Как правило идеально подходит для быстрых разовых трансформаций, например, у нас были собранный руками датасет в виде tsv, а процессор принимал на вход jsonl причем ожидал доп поле “theme”, которого не было в исходном файле (нужного для некоторых вещей, которые были не критичны для текущих подсчетов) — итого, был написан простой однострочник:

cat groups.tsv | awk '{ printf "{\"group\": \"%s\", \"theme\": \"manual\" }\n", $1 }' > group.jsonl

По сути он брал файлик и каждую строчку заворачивал json с нужными полями.

Ссылка с tutorial.

wget — универсальный command line downloader

Регулярно скрипты и пайплайн должны что-то откуда-то подтянуть и качнуть — и wget не подводит: умеет докачивать, авторизовываться, proxies, cookies да еще и помимо http(s) умеет в ftp.

Швейцарский нож в скачивании.

HSTR — поиск по истории команд, с человеческим лицом

Сommand history: hstr

Регулярно мне приходится искать что-то в истории команд:

  • «Это уже приходилось делать»
  • «А с каким ключам запускается Х?»
  • «А вот этот кусок можно и переиспользовать»

Поэтому мне довольно критично иметь хороший и удобный поиск по истории команд, пока hstr полностью со своей задачей справляется:

Полезное, но не вошедшее

В финале я бы упомянул полезными — но тянущими на отдельную статью темы — полезно глянуть: 

  • Связку ssh + tmux + vim (neo, plugins, etc)
  • Базовые знания command line git + git hooks
  • Data pipeline construction make/just
  • Python virtual environments
  • Docker

Показать больше

Похожие публикации

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Кнопка «Наверх»