Русский
Русский
English
Статистика
Реклама

Инфографика

Кто есть кто в кампании за отмену Столлмана

27.04.2021 20:11:49 | Автор: admin

Кампания "за отмену Столлмана", начавшаяся с публикации в Medium предоставляет нам множество интересных данных. Так как подписание открытых писем за отмену и в поддержку Столлмана осуществляется на гитхабе, мы можем проанализировать некоторые характеристики обеих сторон, используя статистические данные, которые доступны через API.

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

Следующие предположения можно проверить ("X" может быть как предложением отменить Столлмана, так и выражением его поддержки):

  • Противники X чаще ассоциированы с крупными компаниями чем сторонники

  • Сторонники X чаще и больше коммитят код и этим более полезны сообществу СПО.

  • Противники X значимо реже коммитят в репозитории со свободными лицензиями.

  • Противники X предпочитают Rust (или JS), сторонники предпочитают C (или C++, Python)

  • Противники X в большей степени социально активны, у них есть аккаунты в соц. сетях, твиттере, они часто пишут.

  • Противники X не коммитят код по выходным (работают только в рабочее время, не энтузиасты)

  • Большинство противников X зарегистрированы на гитхабе менее полугода назад

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

Мы создали репозиторий, в котором будет проходить работа. В нем же лежит эта статья, ее копия на Хабре будет актуализироваться по мере добавления пулл-реквестов. Присоединяйтесь к исследованию!

Далее будут детали.

Замечание о научной честности

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

Кампания за отмену Столлмана управляется из одного центра

Репозиторий противников Столлмана был создан 23 Mar 2021 10:42:36 AM PDT, сторонников - 23 Mar 2021 01:23:39 PM PDT. Видно, что репозиторий противников практически сразу начал активно набирать звезды. У репозитория сторонников был длительный период, когда звезды набирались медленно, но потом (видимо после публикации в соц сетях) процесс пошел много быстрее и количество звезд быстро обогнало противников.

Код
$ cat get-stars.sh#!/bin/bashset -uepage=1owner_repo=$1while true; do    curl -s -H "Authorization: token $GITHUB_OAUTH_" \\        -H "Accept: application/vnd.github.v3.star+json" \\        "<https://api.github.com/repos/$owner_repo/stargazers?per_page=100&page=$page>"| \\        jq -r .[].starred_at_ | grep . || break    ((page++)) || truedone$ echo "epoch,con" >con.stars.csv$ ./get-stars.sh 'rms-open-letter/rms-open-letter.github.io'|while read a; do date -d $a +%s; done|sort -n|cat -n|awk '{print $2","$1}' >>con.stars.csv$ echo "epoch,pro" >pro.stars.csv$ ./get-stars.sh 'rms-support-letter/rms-support-letter.github.io'|while read a; do date -d $a +%s; done|sort -n|cat -n|awk '{print $2","$1}' >>pro.stars.csv$ join -t, -e '' -o auto -a1 -a2 con.stars.csv pro.stars.csv >joined.stars.csv

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

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

Активность в репозиториях сторонников и противников Столлмана

На момент написания этой статьи было 1345 комиттеров противников и 5000+ коммиттеров сторонников. Скачиваем историю коммитов:

Код
$ cat get-commits.py#!/usr/bin/env pythonimport osimport requestsimport jsonimport sysrepo = sys.argv[1]headers = {'Authorization': 'token {}'.format(os.environ["GITHUB_OAUTH"])}commits = []page = 0while page < 300:    page += 1    data = requests.get('https://api.github.com/repos/{}/commits?per_page=100&page={}'.format(repo, page), headers=headers).json()    if len(data) == 0:        break    commits += dataprint(json.dumps(commits, indent=4))$ ./get-commits.py 'rms-open-letter/rms-open-letter.github.io' >con.commits.json$ ./get-commits.py 'rms-support-letter/rms-support-letter.github.io' >pro.commits.json

Посмотрим на изменение количества коммитов от времени с начала кампаний:

Код
$ jq -r .[].commit.author.date pro.commits.json|sort -u|cat -n|awk '{print $2","$1}'|sed -e 's/T/ *' -e 's/Z/*' >pro.commits.csv$ jq -r .[].commit.author.date con.commits.json|sort -u|cat -n|awk '{print $2","$1}'|sed -e 's/T/ *' -e 's/Z/*' >con.commits.csv$ join -t, -e '' -o auto -a1 -a2 con.commits.csv pro.commits.csv >joined.commits.csv

Видно, что репозиторий сторонников гораздо активнее. Коммитов в репозиторий противников за последнее время практически не было. Репозиторий сторонников продолжает обновляться.

Противники Столлмана ведут кампанию в основном в рабочие дни

Посмотрим на распределение коммитов по дням недели.

Код
$ jq -r .[].commit.author.date con.commits.json |./weekday-from-date.py >con.rms_commits.csv$ jq -r .[].commit.author.date pro.commits.json |./weekday-from-date.py >pro.rms_commits.csv$ join -t, con.rms_commits.csv pro.rms_commits.csv >joined.rms_commits.csv

Aктивность противников Столлмана сильно снижается на выходных, зато в среду мы видим пик. Это можно объяснить тем, что во многих компаниях среда это no meeting day.

Активность сторонников значительно менее вариативная. Коммиты совершаются во все дни недели

Противники Столлмана чаще имеют заполненные профили социальных сетей

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

Код
$ jq -r .[].author.login con.commits.json|sort -u >con.logins$ jq -r .[].author.login pro.commits.json|sort -u >pro.logins$ cat get-user-events-data.sh#!/bin/bashset -uescript_dir=$(dirname $(realpath $0))get_data() {    local data_dir=$script_dir/$1 userdata events    for x in $(cat $1.logins); do        userdata=$data_dir/$x.userdata        [ -r $userdata ] && continue        curl -s -H "Authorization: token $GITHUB_OAUTH" "<https://api.github.com/users/$x>" >$userdata        sleep 1        events=$data_dir/$x.events        [ -r $events ] && continue        curl -s -H "Authorization: token $GITHUB_OAUTH" "<https://api.github.com/users/$x/events?per_page=100>" >$events        sleep 1    done}get_data $1$ ./get-user-events-data.sh con$ ./get-user-events-data.sh pro

Пример данных юзера, выгруженных из гитхаба:

Код
{  "login": "zyxw59",  "id": 3157093,  "node_id": "MDQ6VXNlcjMxNTcwOTM=",  "avatar_url": "https://avatars.githubusercontent.com/u/3157093?v=4",  "gravatar_id": "",  "url": "https://api.github.com/users/zyxw59",  "html_url": "https://github.com/zyxw59",  "followers_url": "https://api.github.com/users/zyxw59/followers",  "following_url": "https://api.github.com/users/zyxw59/following{/other_user}",  "gists_url": "https://api.github.com/users/zyxw59/gists{/gist_id}",  "starred_url": "https://api.github.com/users/zyxw59/starred{/owner}{/repo}",  "subscriptions_url": "https://api.github.com/users/zyxw59/subscriptions",  "organizations_url": "https://api.github.com/users/zyxw59/orgs",  "repos_url": "https://api.github.com/users/zyxw59/repos",  "events_url": "https://api.github.com/users/zyxw59/events{/privacy}",  "received_events_url": "https://api.github.com/users/zyxw59/received_events",  "type": "User",  "site_admin": false,  "name": "Emily Crandall Fleischman",  "company": "Commure",  "blog": "",  "location": null,  "email": "emilycf@mit.edu",  "hireable": null,  "bio": null,  "twitter_username": null,  "public_repos": 24,  "public_gists": 0,  "followers": 2,  "following": 12,  "created_at": "2012-12-31T05:33:30Z",  "updated_at": "2021-03-14T01:53:51Z"}

В таблице ниже приводится процент пользователей, у которых заполнены поля twitter_username, company, bio и blog:

поле

противник

сторонник

twitter_username

31%

8%

company

48%

20%

bio

53%

31%

blog

63%

31%

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

Противники Столлмана активнее на гитхабе

Посмотрим на поля public_repos, public_gists, followers и following:

поле

противник

стронник

среднее

медиана

среднее

медиана

public_repos

62

34

21

9

public_gists

18

4

4

0

followers

105

23

16

2

following

30

8

14

1

Противники Столлмана активнее сторонников на гитхабе. У них в среднем больше followers, публичных репозиториев, они также чаще фолловят другие репозитории. Также у противников соотношение followers / following больше 3, в то время как у сторонников оно составляет 1.1.

Противники Столлмана не коммитят в гитхаб на выходных

Воспользуемся полем events_url, чтобы скачать историю действий юзеров.

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

Код
cat weekday-from-date.py#!/usr/bin/env python                                                                                                                                                                                                                                                                                          import datetime                                                                                                                                         import sys                                                                                                                                                                                                                                                                                                      out = [0] \* 7                                                                                                                                          total = 0                                                                                                                                                                                                                                                                                                       for line in sys.stdin.readlines():                                                                                                                          weekday = datetime.datetime.strptime(line.strip(), '%Y-%m-%dT%H:%M:%SZ').weekday()                                                                      out[weekday] += 1                                                                                                                                       total += 1                                                                                                                                                                                                                                                                                                  for day, count in enumerate(out):                                                                                                                           print("{},{}".format(day, count / total))                                                                                                                                                                                                                                                                   $ jq -r .[].created<sub>at</sub> con/\*.events|./weekday-from-date.py >con.event<sub>day.normalized.csv</sub>                                             $ jq -r .[].created<sub>at</sub> pro/\*.events|./weekday-from-date.py >pro.event<sub>day.normalized.csv</sub>                                             $ join -t, con.event<sub>day.normalized.csv</sub> pro.event<sub>day.normalized.csv</sub> 

Видно, что тренд сохранился: активность противников резко снижается на выходных. Можно предполагать, что они используют гитхаб на работе и, возможно, работают над open source проектами за зарплату. Если это предположение верно, их мнение может быть обусловлено отбором, который проводят компании, нанимающие программистов для работы над open source проектами.

Подробнее..

Продажа корочек. Стоимость сертификатов в инфобезе и маршрут их получения

12.11.2020 22:13:22 | Автор: admin

Security Certification Progression Chart 7.0, октябрь 2020 года

Специалист по информационной безопасности Пол Джерими (Paul Jerimy) проделал большую работу и составил обширную схему с порядком получения сертификатов во всех областях ИБ: Security Certification Progression Chart. На сегодняшний день она включает в себя 362 программы сертификации.

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

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

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

Схема читается снизу вверх.

Сертификаты внизу самый начальный уровень. Чем выше вы поднимаетесь, тем более продвинутые сертификаты.

Например, специальность Безопасность сетей и коммуникаций. На нижнем уровне представлены самые базовые экзамены F5 Big-IP Certified Administrator за $135 и CompTIA Network+ за $319, а на вершине пирамиды сертифицированный эксперт по внедрению решений Cisco в области безопасности (CCIE Sec) $2050 за корочку плюс около $12 тыс. транспортные расходы и сертифицированный архитектор Cisco (CCAr). Высочайшее звание в иерархии Cisco стоит $15 тыс. за экзамен.



Первая версия таблицы вышла в марте 2020 года, с тех пор она значительно дополнена и уточнена. Сертификаты в иерархии расположены субъективно, с учётом их авторитетности и мнения реальных экспертов что действительно важно, а что не очень.

Восемь цветов на диаграмме это восемь областей безопасности согласно классификации (ISC), Международного консорциума по сертификации в области безопасности информационных систем, который поддерживает сертификацию CISSP. Некоторые сертификаты охватывают несколько областей, поэтому распределены по нескольким столбцам, но окрашены цветом доминирующего домена.

Области безопасности обычно разбиты на подобласти. Они представлены затенёнными областями внутри основных столбцов. Например, область Операции безопасности (Security Operations) включает пентестинг и применение экплоитов, а уже ближе к программному обеспечению синим цветом обозначены такие подобласти операций безопасности, как Форензика (Криминалистика) и Разбор инцидентов.



В общем, для обычной карьеры рекомендуется только одна сертификация на каждые 3-5 строк в определённой области. Нет особого смысла получать примерно такой же сертификат близкого уровня к тому, что уже есть.

Кроме того, если в своей карьере вы собираетесь ограничиться только одним или двумя сертификатами, то Пол Джерими рекомендует выбрать такие, что охватывают несколько областей, как GSEC (GIAC Security Essentials) или CASP+ (CompTIA Advanced Security Practitioner).

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

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

Хотя на самом деле у большинства профессионалов по информационной безопасности очень мало таких сертификатов, а у некоторых вообще нет ни одного. Как и диплом вуза, эти сертификаты зачастую имеют сомнительную ценность. Но у каждого свой путь. В каком-то смысле сертификация может выступать более практичной альтернативой традиционному высшему образованию или дополнением к нему.
Подробнее..

Визуализация сложных данных с использованием D3 и React

15.10.2020 16:12:34 | Автор: admin

Существует много возможный вариантов реализации сложных графиков в ваших проектах. Я за несколько лет попробовал все возможные варианты. Сначала это были готовые библиотеки типа AmCharts 4. AmCharts сразу же оказался большим и неповоротливым. После этого были более гибкие и дружелюбные библиотеки, такие как Recharts. Recharts был поначалу очень хорош, но со временем сложные фичи создавались такими костылями, которые даже показывать стыдно, а какие-то фичи и вовсе были невозможны в реализации. Таким образом, я пришел к D3 и решаю на нем любые задачи, связанные с графиками. Иногда это занимает немного больше времени по сравнению с готовыми инструментами. Но остается одно неоспоримое преимущество мы всегда знаем, что никогда не упремся в рамки и ваш код не захочется отправить в помойку через пару месяцев.


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




Посмотреть на результат (спойлер)

Сложные данные


Под сложными данными в контексте этой статьи я подразумеваю данные, которые тяжело воспринимать каким-то простым способом (текстом, списком или таблицей). Поэтому для визуального восприятия различной информации мы используем определённые типы графиков.


Пару примеров эффективного восприятия информации:


  • если нужно узнать как цифры ведут себя в течение какого-то временного периода, то стоит выбрать линейные или столбчатые диаграммы;
  • для акцента на соотношение значения лучше использовать круговые диаграммы;
  • если нужно понять как одни показатели влияют на другие, то можно использовать смешанные виды графиков на одной оси;
  • и так далее, чего только не бывает.

Что из себя представляет D3


D3.js это javaScript библиотека для обработки и визуализации данных. Она включает в себя функции для масштабирования, утилиты для манипуляции с данными и DOM-узлами.


При этом, скажу сразу, что большая часть этой библиотеки уже устарела, и ее не стоит использовать. Именно ту часть, где идут манипуляции с DOM узлами, эту задачу мы будем максимально перекладывать на React.


1. Абстрагирование от физических размеров


Я не просто так начинаю с этого пункта. Самое первое, что необходимо сделать, когда приступаем к разработке графика это абстрагироваться от физических размеров. Ну скажем, чтобы мы могли получать координаты точек и сразу же записывать их в атрибуты. Соответственно, нам нужны какие-то методы, которые получают на вход значение или название категории, а на выходе отдают координаты в пикселях.


getY(`значение`); \\ возвращает координату по оси y в пикселяхgetX(`название категории`); \\ возвращает координату по оси x в пикселях

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


К счастью в D3 это сделать очень просто.


Получение координат по оси Y (ось значения)


На изображении показано положение точек из массива [4, 15, 28, 35, 40] в контейнере выстой 300px:



Теперь посмотрите как с помощью D3 создать функцию для получения физических координат для отрисовки этих точек:


const getY = d3.scaleLinear()  .domain([0, 40])  .range([300, 0]);

Мы создаем функцию getY с помощью D3 функции scaleLinear(). В метод domain передаем область данных, а в range передаем физические размеры от 300px до 0px. Так как в svg отчет начинается с левого верхнего угла, то нужно именно в таком порядке передавать аргументы в range сначала 300, потом 0.


Мы только один раз работаем с физическими размерами, когда создаем эту функцию и передаем в нее высоту графика. После этого мы работаем только с реальными данными и сразу же выводим полученные размеры в svg атрибуты.


Пример применения функции getY:


getY(4);  // 270getY(15); // 187.5getY(28); // 90getY(35); // 37.5getY(40); // 0

В качестве аргумента мы передаем значение, а на выходе получаем координату по оси y. Обратите внимание, что это отступ сверху контейнера.


Получение координат по оси X (ось категории)


Аналогичная ситуация по оси X. Мы хотим один раз подвязаться к категориям, а дальше передавать название категории и получать ее координаты.


На изображении мы видим контейнер шириной 600px и 5 месяцев. Месяца будут служить подписями по оси X:



Создадим такую функцию:


const getX = d3.scaleBand()  .domain(['Jan', 'Feb', 'Mar', 'Apr', 'May'])  .range([0, 600]);

Мы используем функцию scaleBand из D3. В domain мы передаем все возможные категории в нужном порядке, а в range область, выделенную под график.


Смотрим пример применения нашей функции getX:


getX('Jan'); // 0getX('Feb'); // 120getX('Mar'); // 240getX('Apr'); // 360getX('May'); // 480

В качестве аргумента мы передаем название категории, а на выходе получаем координату по оси X (отступ слева).


2. Отрисовка простых фигур


С использованием наших функций для получения координат мы уже можем рисовать простые фигуры на координатной плоскости. К простым фигурам в текущем контексте я отношу:


  • rect прямоугольник;
  • circle круг;
  • line линия;
  • text обычный блок текста.

Эти фигуры схожи тем, что они принимают 1 или 2 координаты и просто содержат разные физические свойства (цвет, размер и прочее). Остальные фигуры создаются более сложным путем, об этом позже.


Точки


Для примера попробуем нарисовать точки с использованием svg-фигуры circle:


const data = [  { name: 'Jan', value: 40 },  { name: 'Feb', value: 35 },  { name: 'Mar', value: 4 },  { name: 'Apr', value: 28 },  { name: 'May', value: 15 },];return (  <svg width={600} height={300}>    {data.map((item, index) => {      return (        <circle          key={index}          cx={getX(item.name) + getX.bandwidth() / 2}          cy={getY(item.value)}          r={4}          fill="#7cb5ec"        />      );    })}  </svg>);

Фигура circle абсолютно примитивна. В данном случае она принимает координаты центра cx, cy, радиус r и цвет заливки fill.


Здесь мы использовали новый метод bandwidth:


getX.bandwidth()

Данный метод возвращает ширину колонки расстояние от одного месяца до соседнего. Мы применяем этот метод для того, чтобы сдвинуть наши точки до центра колонки:


getX(item.name) + getX.bandwidth() / 2

Вот, что у нас получится в результате:



Подписи


Для создания текстовых узлов в svg используется фигура text. Она также принимает координаты и содержит свои личные атрибуты для стилизации.


Подпишем значения на наших точках:


return (  <svg ...>    {data.map((item, index) => {      return (        <g key={index}>          <circle ... />          <text            fill="#666"            x={getX(item.name) + getX.bandwidth() / 2}            y={getY(item.value) - 10}            textAnchor="middle"          >            {item.value}          </text>        </g>      );    })}  </svg>);

Что здесь нового? Мы обернули наш круг и текст элементом g. Элемент g один из самых распространенных в svg, обычно он просто группирует элементы и двигает их вместе при необходимости через свойство transform.


Вот как выглядят наши подписи к точкам:



3. Оси


Для осей существуют готовые элементы в D3.


const getYAxis = ref => {  const yAxis = d3.axisLeft(getY);  d3.select(ref).call(yAxis);};const getXAxis = ref => {  const xAxis = d3.axisBottom(getX);  d3.select(ref).call(xAxis);};return (  <svg ...>    <g ref={getYAxis} />    <g      ref={getXAxis}      transform={`translate(0,${getY(0)})`} // нужно сдвинуть ось в самый низ svg    />    ...  </svg>);

Вот что получается, если ничего не менять и не настраивать:



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


const getYAxis = ref => {  const yAxis = d3.axisLeft(getY)    .tickSize(-600) // ширина горизонтальных линий на графике    .tickPadding(7); // отступ значений от самого графика  d3.select(ref).call(yAxis);};const getXAxis = ref => {  const xAxis = d3.axisBottom(getX);  d3.select(ref).call(xAxis);};return (  <svg  ...>    <g className="axis" ref={getYAxis} />    <g      className="axis xAxis"      ref={getXAxis}      transform={`translate(0,${getY(0)})`}    />    ...  </svg>);

И немного стилей:


.axis {  color: #ccd6eb;  & text {    color: #666;  }  & .domain {    display: none;  }}.xAxis {  & line {    display: none;  }}

Посмотрим как сейчас выглядит наш пример:



4. Отрисовка сложных фигур


У svg нет каких-то встроенных простых методов для построения кривых по точкам, секций круга и так далее. Это достаточно сложный процесс на низком уровне. D3 предоставляет методы для построения таких сложных фигур.


Кривые линии


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


const linePath = d3  .line()  .x(d => getX(d.name) + getX.bandwidth() / 2)  .y(d => getY(d.value))  .curve(d3.curveMonotoneX)(data);// M60,0C100,6.25,140,12.5,180,37.5C220,62.5,260,270,300,270C340,270,380,90,420,90C460,90,500,138.75,540,187.5

В качестве аргумента line() мы передаем наш массив с данными data, а D3 уже под капотом проходится по этому массиву и вызывает функции для поиска координат, которые мы передали в методы x и y. В curve мы передаем тип линии, в данном случае это curveNatural (таких типов достаточно много).


Теперь немного разберем полученную строку. Команда M используется в строки для указания точки, откуда нужно начать рисовать. Команда С это кубическая кривая Безье, которая принимает три набора координат, по которым строит кривую. Подробнее можно почитать здесь https://developer.mozilla.org/ru/docs/Web/SVG/Tutorial/Paths.


Теперь просто вставляем полученную строку в качестве атрибута d для элемента path:


return (  <svg  ...>        <path      strokeWidth={3}      fill="none"      stroke="#7cb5ec"      d={linePath}    />    </svg>);

Path одна из самых распространенных фигур в svg из которой можно сделать практически что угодно. Мы еще будем использовать эту фигуру дальше.


Смотрим на результат:



Замкнутые области


Теперь мы попробуем построить замкнутую области с одной кривой стороной. Она будет использоваться в качестве заливки для графика.


В построении области с кривой стороной похожая ситуация, как и с кривой линией. Здесь используется функция area, а методов становится больше, потому что нужно передать отдельно функцию для поиска нижней линии. Если нам нужна прямая нижняя линия, то просто передаем нулевое значение по низу.


const areaPath = d3.area()  .x(d => getX(d.name) + getX.bandwidth() / 2)  .y0(d => getY(d.value))  .y1(() => getY(0))  .curve(d3.curveMonotoneX)(data);// M60,300C100,300,140,300,180,300C220,300,260,300,300,300C340,300,380,300,420,300C460,300,500,300,540,300L540,187.5C500,138.75,460,90,420,90C380,90,340,270,300,270C260,270,220,62.5,180,37.5C140,12.5,100,6.25,60,0Z

На выходе также получаем путь, который нужно передать в фигуру path. Здесь в конце пути появляется новая команда Z, которая замыкает контур, рисуя прямую линию от текущего положения обратно к первой точке пути. А также в середине строки есть команда L, которая рисует прямую линию от текущей точки.


Добавляем полученную строку в path:


return (  <svg  ...>        <path      fill="#7cb5ec"      d={areaPath}      opacity={0.2}    />      </svg>);

Смотрим на нашу красоту:



5. События


Мы игнорируем все методы для навешивания событий из D3. Эту задачу мы также перекладываем на React и вешаем все события прям в разметке JSX. А для хранения состояний используем знакомый всем хук useState.


Эффект наведения


Подробнее рассмотрим эффект наведения, остальные события делаются аналогично.


Наша задача сделать эффект увеличения точки при наведении на всю область категории. Так как у нас нет определенного прямоугольника в DOM, на которое можно повесить событие напрямую, то мы будем вешать событие на всю svg, а затем вычислять позицию.


Но для начало заведем состояние активной категории:


// null  если ничего не активно (по умолчанию)const [activeIndex, setActiveIndex] = useState(null);

После этого пишем наш обработчик:


const handleMouseMove = (e) => {  const x = e.nativeEvent.offsetX; // количество пикселей от левого края svg  const index = Math.floor(x / getX.step()); // делим количество пикселей на ширину одной колонки и получаем индекс  setActiveIndex(index); // обновляем наше состояние};return (  <svg        onMouseMove={handleMouseMove}  ></svg>)

И добавим событие, которое будет сбрасывать активный индекс, когда мы убираем мышку с svg:


const handleMouseMove = (e) => {  };const handleMouseLeave = () => {  setActiveIndex(null);};return (  <svg        onMouseMove={handleMouseMove}    onMouseLeave={handleMouseLeave}  ></svg>)

Рабочее состояние есть, теперь просто говорим, что нужно рисовать если индекс активный, а что, если нет:


data.map((item, index) => {  return (    <g key={index}>      <circle        cx={getX(item.name) + getX.bandwidth() / 2}        cy={getY(item.value)}        r={index === activeIndex ? 6 : 4} // при наведении просто немного увеличиваем круг        fill="#7cb5ec"        strokeWidth={index === activeIndex ? 2 : 0} // обводка появляется только при наведении        stroke="#fff" // добавили белый цвет для обводки        style={{ transition: `ease-out .1s` }}      />          </g>  );})

И теперь смотрим на результат:



Итог


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



D3 это мощный инструмент, но существенная часть библиотеки устарела, поэтому нужно выбирать те вещи, которые действительно нам облегчат жизнь. Соответственно, мы берем из D3 только функции для масштабирования и методы для создания сложных фигур.


Мы выкидываем из D3 все устаревшие методы для прямой манипуляции элементами DOMа и делам это как знали и умели до этого.


В интернете будет много примеров, которые будут сбивать вас с толку и заставлять писать в стиле jQuery, будьте внимательны. Надеюсь эта статья вам поможет сделать всё красиво!

Подробнее..

Как я пытался придумать новый подход к изучению алгоритмов через интерактивные визуализации

16.06.2021 22:19:34 | Автор: admin

Представьте человека, который изучает алгоритмы. Чтобы понять как они работают, приходится изучать их код и представлять, как компьютер будет его выполнять. Это странно почему мы должны учиться думать как компьютер, вместо того, чтобы заставить его помогать нам учиться? Какая-то сильная технозависимость.

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

В результате родился проект Объясняем код. Посмотреть, что это такое можно на code-explained.com. Код проекта выложен на Гитхаб.

Чем я вдохновлялся

Брет Виктор говорит, что творцам нужна мгновенная обратная связь с тем, что они делают. Когда вы создаете что-то или вносите изменения в свое творение, то должны сразу же видеть результат. Иначе, часть идей просто никогда не придут к вам в голову.

Например, если вы редактируете программный код, то результат должен отображаться в реальном времени, без повторной компиляции. Иначе, вы не увидите промежуточные состояния, и у вас не родятся связанные с ними идеи. Я не буду подробно пересказывать эту мысль, тем более, что на Хабре уже подробно о ней рассказали. Почитайте, если еще не успели.

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

Как сегодня изучают алгоритмы

Преподаватель записывает на доске код, а потом по шагам объясняет, как он работает.

В видео на Youtube происходит нечто подобное ведущий берет код алгоритма и отрисовывает этапы его работы

На ИТ-ресурсах создают анимации.

А кто-то даже пытается объяснить работу алгоритма через танец.

Почему эти подходы казались мне неэффективными

У всех перечисленных подходов есть огромный минус. Они пытаются заставить нас думать как компьютер, а не наоборот подчинить железо нашим потребностям. Чтобы понять, как работает код алгоритма, нужно представлять, как машина будет его выполнять. Я решил, что хочу уйти от этого подхода.

Как я перешел от технозависимости к человечности

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

Вместе с командой мы разработали проект Объясняем код. Это такой интерактивный учебник, который с помощью визуализаций объясняет, как работают алгоритмы.

Выглядит это как-то так. Можно вводить свои данные. А затем с помощью плеера запускать и останавливать исполнение кода, перематывать его вперед и назад. При этом визуализация в реальном времени показывает, что делает алгоритм.

Как это технически реализовано

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

Чтобы сэкономить на копировании данных, я применил Immutable.js. Immutable.js это библиотека неизменяемых коллекций. Модификации таких коллекций всегда возвращают новую коллекцию, которую легко сохранить. Так я избегаю глубокого копирования. Не буду вдаваться в подробности, на Хабре про immutable.js уже писали. Для примера кусочек кода с итерированием по хеш-таблице:

while (true) { // Итерируемся по списку    this.addBP('check-not-found'); // Метод сохраняем состояние    if (this.newList.get(this.newListIdx) === null) {        // this.newList -- это немутабельный список        break;    }    this.addBP('check-found'); // Выполнена очередная строчка, сохраняем состояние    if (EQ(this.newList.get(this.newListIdx), this.number)) {        this.addBP('found-key');        return true;    }    this.fmtCollisionCount += 1; // Для динамических комментариев иногда нужно сохранять статистикуу    this.newListIdx = (this.newListIdx + 1) % this.newList.size; // Переходим к следующему индекксу    this.addBP('next-idx');}

В любой момент пользователь может отмотать время слайдером, и мы должны быть готовы анимировать переход. Поэтому анимации сделаны декларативно на React и CSS. На React описываются нужное состояние, а CSS transitions автоматически высчитывают и анимируют переход. Это позволяет избежать совсем сложного императивного кода с запутанным состоянием и ручными вычислениями. Получается тоже не просто, и в итоге анимациями заведует огромный класс на 1000 строк. Но я уверен, что императивно реализовать то же самое у меня вообще не получилось бы.

Много строк возникает из-за особенностей браузерных API и производительности в разных браузерах. Например, большой проблемой оказалось сделать так, чтобы браузеры не склеивали последовательные изменения друг с другом. Если добавить div с определённой начальной позицией, и потом сразу же поменять координаты на конечные, то браузер склеит эти два изменения в одно. Div сразу окажется в конечной позиции без анимации. Чтобы такое не происходило, приходится вставлять задержку в два фрейма анимации с помощью window.requestAnimationFrame().

Если вам интересно подробнее про техническую реализацию, напишите об этом в комментариях. Я сделаю более подробный пост про техническую реализацию.

Код проекта на гитхабе

Что дальше?

Мы запустились недавно и пока рассказали только про хеш-таблицы. Проект растет и развивается и в нем будут появляться новые главы в планах сортировки и другие алгоритмы. Нам очень нужна обратная связь расскажите про ваши впечатления, что на ваш взгляд стоит изменить или доработать. Напоминаю, что проект можно посмотреть по ссылке.

Подробнее..

Из песочницы Кому на Руси жить хорошо? Как мы искали самый зеленый город с помощью OpenStreetMap и Overpass API

24.09.2020 16:22:36 | Автор: admin
У каждой карты есть легенда: именно она говорит читателю о том, что и каким образом на ней обозначено. Домам соответствуют многоугольники серого цвета, дорогам отрезки и кривые, территории парков и скверов заливаются светло-зеленым и украшаются пиктограммой дерева. А к некоторым картам добавляют полезное приложение список этих самых дорог с протяженностью, количество парков, лавочек и мусорных урн.

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

Использование картографии в целом помогает ускорить время реакции и принятия решений по экстренным вопросам, упрощает процесс планирования и прогнозирования, а главное вся информация доступна в максимально наглядном виде.

В ходе работы с одним из заказчиков перед нами возникла интересная задача подсчитать количество объектов на карте по категориям.

Найти


Определить самый зеленый город в ЦФО по совокупности следующих данных: количество лавочек, урн и парков.

Дано


Картография. В качестве плацдарма мы выбрали OpenStreetMap (далее OSM) по весьма простой причине Open Source.

Решение


Существует несколько подходов к решению поставленной задачи. К примеру, мы можем использовать PostgreSQL для осуществление запросов к базе данных OSM и получения необходимых данных, или использовать QGIS систему для создания, анализа и публикации геопространственной информации. Однако, мы нашли более элегантный и эффективный способ Overpass API.

Overpass API мощный инструмент для извлечения данных из базы OSM по запросу пользователя. Он оптимизирован для задач любого масштаба: от получения нескольких элементов из базы до сотен миллионов объектов, которые отбираются согласно запросу в виде XML или Overpass QL модернизированной версии Overpass XML. Подробнее об Overpass API здесь.
Будем начинать все с чистого листа: в первую очередь потребуется развернуть OSM на сервере. В качестве операционной системы на нашей машине используется Ubuntu.

Q: Зачем разворачивать свой OSM?
A: Для работы с данными нам потребуется Overpass API, общедоступный сервер которого имеет ограничение на количество запросов в сутки. Именно по этой причине мы развернем свой сервер с блекджеком OSM и Overpass API.
Подробная инструкция по установке OSM лежит здесь.
Следующим шагом мы устанавливаем Overpass API его последний релиз можно найти тут.

sudo apt-get updatesudo apt-get install g++ make expat libexpat1-dev zlib1g-dev apache2 -ywget http://dev.overpass-api.de/releases/osm-3s_ВЕРСИЯ.tar.gztar -zxvf osm-3s_ВЕРСИЯ.tar.gzcd osm-3s_ВЕРСИЯ./configure CXXFLAGS="-O2" --prefix=$EXEC_DIRmake installcd ../chmod -R 755 ./overpass

После установки потребуется провести populating создание базы данных. База данных всего мира нам не нужна, поэтому мы воспользуемся сервисом Geofabrik, который позволяет получить данные по заданным административным регионам.
Достойная альтернатива Geofabrik BBBike.

Мы загружаем и распаковываем базу данных, загруженную из каталога Europe > Russian Federation > Central Federal District в формате .osm.bz2, по следующей схеме:
ПУТЬ_К_INIT_OSM3S.SH ПУТЬ_К_ФАЙЛУ_BZ2 ПУТЬ_КУДА_РАСПАКОВВАТЬ ДИРЕКТОРИЯ_OVERPASS_API
Примечание: в данном случае все действия выполняются в каталоге overpass.

Итак, платформа практически готова сейчас мы можем сделать свой первый запрос и узнать количество парков в целом по региону.
ПУТЬ_К_OSM3S_QUERY --db-dir = ПУТЬ_К_DB

Наш запрос и ответ выглядят следующим образом:

root@MIP-USER55:~# cd overpass/root@MIP-USER55:~/overpass# ./osm-3s_v0.7.56.7/bin/osm3s_query --db-dir=dbencoding remark: Please enter your query and terminate it with CTRL+D.[out:json][timeout:25];(nwr["landuse"="forest"];);out count;{  ...,  "elements": [{  "type": "count",  "id": 0,  "tags": {    "nodes": "23",    "ways": "19723",    "relations": "4206",    "total": "23952"  }}  ]}

Мы уже близко: осталось только разбить парки по областям и городам. Справиться с этой задачей нам поможет отдельно запущенный и постоянно работающий Dispatcher.

Запускаем API и в директории /etc/apache2/ports.conf добавляем Listen ПОРТ.

echo "ИМЯ_СЕРВЕРА localhost" | sudo tee /etc/apache2/conf-available/ИМЯ_СЕРВЕРА.conf && sudo a2enconf ИМЯ_СЕРВЕРАsudo iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport ПОРТ -j ACCEPTsudo a2enmod cgisudo a2enmod ext_filtersudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/ИМЯ_КОНФИГА_ДЛЯ_СЕРВЕРА.conf

Проверяем конфигурацию. Она должна выглядеть следующим образом.

<VirtualHost *:ПОРТ>   ServerAdmin webmaster@localhost   ExtFilterDefine gzip mode=output cmd=/bin/gzip   DocumentRoot ПУТЬ_К_OVERPASS_API/html   ScriptAlias /api/ ПУТЬ_К_OVERPASS_API/cgi-bin/   <Directory "ПУТЬ_К_OVERPASS_API">      AllowOverride None      Options Indexes FollowSymLinks      Require all granted   </Directory>   <Directory "ПУТЬ_К_OVERPASS_API/cgi-bin/">      AllowOverride None      Options +ExecCGI -MultiViews +SymLinksIfOwnerMatch      Require all granted   </Directory>   ErrorLog ${APACHE_LOG_DIR}/error.log   CustomLog ${APACHE_LOG_DIR}/access.log combined</VirtualHost>

Далее включаем новый хост и отправляем старый отдыхать.

sudo a2ensite КОНФИГ.confsudo a2dissite 000-default.confsudo a2dissite ВСЕ_ДРУГИЕ_КОНФИГИ.confsudo service apache2 reload

Настало время включить первый Dispatcher, который будет обрабатывать наши запросы. Для этого воспользуемся командой.

nohup ПУТЬ_К_OVERPASS_API/bin/dispatcher --osm-base --db-dir=ПУТЬ_К_DB --meta &

Первый признак того, что все пошло по плану создание файла
osm3s_OVERPASS_API_ВЕРСИЯ_osm_base в директории с базой данных. В файле nohup.out появится сообщение о статусе Dispatcher dispatcher just started.

Однако, работа на этом не заканчивается: требуется запустить ещё один Dispatcher. Для начала копируем папку rules в директорию с базой данных и раздаем права на появившийся в результате файл osm3s_OVERPASS_API_ВЕРСИЯ_areas.

nohup ПУТЬ_К_OVERPASS_API/bin/dispatcher --areas --db-dir=ПУТЬ_К_DB &chmod 666 "../db/osm3s_OVERPASS_API_ВЕРСИЯ_areas"nohup ПУТЬ_К_OVERPASS_API/bin/rules_loop.sh ПУТЬ_К_DB &

Теперь мы можем сделать запрос по области и подсчитать количество парков в Рязани. И, кстати, это уже работает в адресной строке браузера.

http://localhost:ПОРТ/api/interpreter?data=[output:json][timeout:25]; area[name="Рязань"]->.searchArea; ( nwr["leisure"="park"](area.searchArea); ); out count;

Долгожданный ответ!

"elements": [{  "type": "count",  "id": 0,  "tags": {    "nodes": "0",    "ways": "57",    "relations": "11",    "areas": "0",    "total": "68"  }}  ]}

Итак, теперь мы можем погрузиться в аналитику и вопросы благоустройства: найдем количество парков, лавочек и мусорных баков в 25 крупных городах ЦФО и сравним эти показатели при помощи аналитических инструментов платформы ODANT.
ODANT цифровая интеграционная платформа отечественной разработки, предназначенная для построения информационных систем различной сложности и распределенности. Подробнее об ODANT здесь.
Так выглядят наши параметры для поиска урн: в рамках задачи мы не делаем различий между контейнерными площадками, отдельно стоящими урнами и пунктами приема ТБО.

nwr["amenity"="recycling"](area.searchArea);nwr["amenity"="waste_disposal"](area.searchArea);nwr["amenity"="waste_basket"](area.searchArea);

Выходные данные мы экспортировали из ODANT в виде плоской таблицы.

Город


Урны


Население


Население/Урны


Владимир


1525


356937


234


Красногорск


274


175554


641


Калуга


376


332039


883


Тамбов


279


292140


1047


Москва


11473


12678079


1105


Коломна


111


140129


1262


Балашиха


378


507366


1342


Курск


336


452976


1348


Рыбинск


129


184635


1431


Мытищи


140


235504


1682


Люберцы


119


205295


1725


Зеленоград


140


250453


1789


Воронеж


544


1058261


1945


Тверь


225


449507


1998


Ярославль


273


608353


2228


Муром


43


106984


2488


Подольск


114


308130


2703


Химки


89


259550


2916


Кострома


72


276929


3846


Липецк


124


509420


4108


Рязань


118


539290


4570


Королёв


49


224348


4579


Тула


101


475161


4705


Электросталь


32


156026


4876




В данном рейтинге город Владимир занимает почетную первую строчку: на одно место скопления мусора там приходится всего 234 человека. Используя встроенные инструменты ODANT строим два занятных графика.





Перейдем к следующему элементу лавочкам.

nwr["amenity"="bench"](area.searchArea);

Получаем следующий результат в виде таблицы.

Город


Лавочки


Население


Население/лавочки


Владимир


593


356937


602


Тамбов


413


292140


707


Москва


13970


12678079


908


Красногорск


143


175554


1228


Балашиха


411


507366


1234


Зеленоград


185


250453


1354


Тверь


268


449507


1677


Люберцы


115


205295


1785


Калуга


176


332039


1887


Курск


214


452976


2117


Муром


42


106984


2547


Тула


172


475161


2763


Коломна


49


140129


2860


Воронеж


272


848752


3120


Подольск


79


308130


3900


Рязань


132


539290


4086


Кострома


61


276929


4540


Химки


43


259550


6036


Рыбинск


25


184635


7385


Ярославль


78


608353


7799


Липецк


55


509420


9262


Электросталь


16


156026


9752


Королёв


23


224348


9754


Мытищи


17


235504


13853



И снова Владимир оказался самым благоустроенным из всех претендентов: 602 человека на одну скамейку посадить не получится, но в Мытищах за места идет куда более ожесточенная борьба. Однако, всегда можно придумать расписание.

Визуализируем наши результаты.





Перейдем к самой интересной части: подсчет площади парков. Для решения этой задачи мы можем использовать несколько методов, но самым оупенсорсным и замечательным мы находим библиотеку Leaflet. В самом запросе потребуется заменить out count на out geom, что в результате даст нам координаты областей.
Leaflet библиотека с открытым исходным кодом, написанная на JavaScript, предназначенная для отображения карт на веб-сайтах. Поддерживает большинство мобильных и стационарных платформ из числа тех, что поддерживают HTML5 и CSS3. Leaflet позволяет разработчику, не знакомому с ГИС, легко отображать растровые карты, состоящие из маленьких фрагментов тайлов, с, возможно, дополнительными слоями, накладываемыми поверх основного. Подробнее о Leaflet здесь.

Создадим полигон.

const polygon = L.polygon(КООРДИНАТ).addTo(map);const area = L.GeometryUtil.geodesicArea(polygon.getLatLngs());

Теперь в area лежит площадь региона в м2. Извлекаем данные для выбранных нами городов и получаем следующую таблицу.

Город


Общая площадь парков (km2)


Площадь города (km2)


Процент пространства, занимаемого парками


Кол-во

парков


Зеленоград


4.13


37.199


0.111


26


Калуга


12.60


168.8


0.075


140


Москва


121.75


2561.5


0.048


1469


Люберцы


0.60


12.87


0.047


28


Владимир


4.62


137.14


0.034


104


Химки


3.55


109.8


0.032


27


Подольск


1.29


40.39


0.032


53


Балашиха


1.78


62.8


0.028


55


Тамбов


2.71


96.58


0.028


140


Тула


4.09


145.8


0.028


102


Кострома


3.95


144.5


0.027


50


Красногорск


0.69


25.65


0.027


21


Рязань


4.32


224.163


0.019


96


Ярославль


3.68


205.8


0.018


176


Королёв


0.97


55.47


0.017


30


Курск


3.31


208.2


0.016


862


Коломна


1.03


65.1


0.016


21


Мытищи


0.53


34.59


0.015


30


Воронеж


8.25


596.51


0.014


414


Липецк


4.44


330.15


0.013


78


Тверь


1.38


152.22


0.009


129


Муром


0.33


43.78


0.008


11


Рыбинск


0.65


101.42


0.006


62


Электросталь


0.25


51.45


0.005


52



По данным OSM Зеленоград полностью оправдывает свое название 11% площади города занято зелеными массивами. Получим отношение количества жителей к количеству парков.

Город


Общая площадь парков (м2)


Кол-во м2 парков на 1 жителя


Количество жителей на 1 парк


Калуга


12,600,000


37.95


2372


Зеленоград


4,130,000


16.49


9633


Кострома


3,950,000


14.26


5539


Химки


3,550,000


13.68


9613


Владимир


4,620,000


12.94


3432


Воронеж


8,250,000


9.72


2050


Москва


121,750,000


9.60


8630


Тамбов


2,710,000


9.28


2087


Липецк


4,440,000


8.72


6531


Тула


4,090,000


8.61


4658


Рязань


4,320,000


8.01


5618


Коломна


1,030,000


7.35


6673


Курск


3,310,000


7.31


525


Ярославль


3,680,000


6.05


3457


Королёв


970,000


4.32


7478


Подольск


1,290,000


4.19


5814


Красногорск


690,000


3.93


8360


Рыбинск


650,000


3.52


2978


Балашиха


1,780,000


3.51


9225


Муром


330,000


3.08


9726


Тверь


1,380,000


3.07


3485


Люберцы


600,000


2.92


7332


Мытищи


530,000


2.25


7850


Электросталь


250,000


1.60


3001



Представим данные в виде графиков.





И в финале рейтинг городов, подсчитанный по занимаемым местам.

Город


Рейтинг


Место


Владимир


12


1


Калуга


15


2


Москва


18


3


Зеленоград


21


4


Тамбов


23


5


Красногорск


35


6


Балашиха


39


7


Люберцы


45


8


Химки


46


9


Курск


47


10


Коломна


48


11


Кострома


50


12


Воронеж


52


13


Подольск


55


14


Тула


55


15


Рязань


61


16


Тверь


63


17


Ярославль


63


18


Муром


69


19


Рыбинск


69


20


Липецк


70


21


Королёв


75


22


Мытищи


75


23


Электросталь


94


24



Эпилог и выводы


Решением судейской коллегии в составе OpenStreetMap, Overpass API и ODANT,
г. Владимир занимает почетное первое место и получает титул Самый зеленый в ЦФО.

Стоит отметить следующий факт: наше исследование базировалось исключительно на данных, отраженных в OSM. Естественно, в Мытищах есть еще пара сотен скамеек, да и в Туле куда больше мест для скопления отходов. Наши результаты можно рассматривать с другой стороны, к примеру, для оценки динамики внесения объектов городской инфраструктуры в базу данных OSM. Однако, в среднем люди одинаково медленно вносят данные в OSM, поэтому мы можем считать, что данные сравнительно достоверны и заслуживают внимания.

Нам удалось решить поставленную задачу и найти эффективный способ работы с объектами на картах OSM: им оказалась комбинация Overpass API и Leaflet. С помощью данного набора инструментов мы можем делать запросы к БД OSM и получать данные о количестве объектов, вычислять площади областей. Для представления данных и аналитики мы собрали web-решение на базе ODANT, которое удовлетворило все наши потребности.

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

Ведущий Frontend-разработчик, Инфостандарт Епифанов Даниил.
Редактор, Инфостандарт Морозов Никита.
Подробнее..

Самые популярные языки для локализации в 2021 году обзор от Alconost

24.02.2021 16:18:54 | Автор: admin
Какие языки выбрать для локализации сервиса, приложения или игры?Какие языки выбрать для локализации сервиса, приложения или игры?

Эта информация пригодится вам, если вы планируете вывести свой сервис, приложение или игру на иностранные рынки и пока не определились, какие языки для вас приоритетны. Или если вы уже локализовали свой продукт на ключевые языки и ищете дополнительные рынки, на которых он может выстрелить.

Несколько слов о том, кто мы и почему из нашей статистики можно делать выводы. Мы в Alconost локализуем приложения, игры и веб-сервисы. Наши клиенты и крупные игроки IT-рынка, и небольшие команды, и инди-разработчики. С 2004 года мы помогли 2000 IT-компаний со всего мира вывести их продукты на новые рынки.

Клиенты регулярно спрашивают у нас: На какие языки посоветуете переводить? Ответим с опорой на факты. Мы проанализировали заказы за 2020 год и подготовили для вас статистику, инфографику и аналитику по языкам, которые выбирают наши клиенты.

Для этого обзора рассматривались заказы на перевод с английского языка, выполненные в отделе локализации Alconost.

Топ-12 языков для локализации с английского

В 2020-м клиенты переводили у нас с английского на 89 языков. Подчеркнём, что абсолютное большинство клиентов переводят у нас именно с английского, в то время как локализацию с других языков заказывают менее чем в 3% случаев.

Итак, давайте посмотрим, какие языки самые популярные при переводе сервисов, приложений и игр с английского.

Диаграмма 1. Самые популярные языки для локализации с английскогоДиаграмма 1. Самые популярные языки для локализации с английского

Диаграмма 1. Доля переводов на языки из топ-12 языков составляет 62,3% от общего объёма заказов на локализацию с английского.

Удивлены? Да, локализация даже на все 12 самых популярных языков будет отвечать потребностям лишь 2/3 потенциальной аудитории. Для охвата оставшейся трети понадобится локализация ещё на 70+ языков.

Давайте подробнее рассмотрим топ, а затем сделаем небольшой экскурс в статистику по переводам на менее популярные языки.

Лидеры рейтинга: классика FIGS и не только

Есть 4 языка, которые считаются классикой локализации. Это французский, итальянский, немецкий и испанский. Их даже обозначают аббревиатурой FIGS или, добавляя английский, EFIGS. Переводы с английского на эти языки возглавляют наш топ.

Однозначный лидер французский: каждый 11-й заказ по переводу с английского был именно на этот язык. Популярность итальянского, испанского и немецкого для локализации почти одинакова, но их отставание от лидирующего французского всё же довольно заметно.

Посмотрите, как распределились доли по переводам с английского в лидирующей пятёрке: локализация на французский более 25%, а на три других классических языка в среднем по 19% на каждый.

Диаграмма 2. Пять самых популярных языков для локализации с английского: распределение долейДиаграмма 2. Пять самых популярных языков для локализации с английского: распределение долей

Диаграмма 2. Самые популярные языки для перевода с английского среди клиентов Alconost французский, итальянский, испанский и немецкий.

Но мир становится всё глобальнее, и к европейской классике добавляются новые языки. Для наших клиентов новой классикой локализации в 2020-м стал бразильский португальский: он наступает на пятки лидирующей четвёрке, совсем немного уступая немецкому и испанскому.

Выбор языка или выбор страны?

Интересный факт: бразильский португальский единственный язык в нашем топ-5, не совпадающий со страной происхождения. Так, французский может быть ещё и канадским; к слову, если вас интересует это направление вот наш обзор рынка и советы по локализации для Канады. У испанского несколько разновидностей: взять хотя бы аргентинский, колумбийский и мексиканский. И хотя мы переводим на все эти диалекты (а переводы на мексиканский испанский даже входят в наш топ-20), французский и испанский наши клиенты чаще всего заказывают именно для Европы, а португальский именно для Латинской Америки (Бразилия).

На наш взгляд, вот почему бразильский португальский популярен для локализации. Бразилия входит в топ-10 стран по величине экономики, в топ-3 по показателям загрузок в Google Play и App Store, а ещё в стране высокий уровень покупательной способности. Кстати, мы внимательно изучали рынок мобильных игр и приложений Бразилии; почитайте наш обзор.

Смотрим на Восток

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

Кроме того, нельзя недооценивать и платёжеспособность японского рынка, где ежемесячный ARPU в 5 раз выше китайского. И хотя занять место под солнцем на японском рынке не самая простая задача для иностранного разработчика, возможные трудности не уменьшают привлекательность этой страны для продвижения IT-продуктов.

Что до китайского, то локализация на его упрощённый вариант занимает в нашем рейтинге 8-е место, а переводы на традиционный китайский 13-е.

Диаграмма 3. Локализация с английского на китайский: нюансы Диаграмма 3. Локализация с английского на китайский: нюансы

Диаграмма 3. С английского на упрощённый китайский мы перевели почти в 2 раза больше заказов, чем на традиционный китайский.

Различия между разновидностями китайского разработчики учитывают при выборе региона, в котором планируется продвигать продукт. Так, на упрощённый китайский его ещё называют мандарин переводят для пользователей из материковой части Китая. А на традиционный китайский и его другие диалекты заказывают локализацию для пользователей с Тайваня или из Гонконга.

Обратно на Восток через Нидерланды

Интересно, что между двумя популярными языками азиатского региона японским на 6-м месте и упрощённым китайским на 8-м неожиданно оказался нидерландский. На наш взгляд, есть несколько причин его популярности для локализации. Среди них платежеспособность и развитая Интернет-инфраструктура, а ещё высокая лояльность голландских пользователей к контенту на родном языке.

К слову, любопытный факт о геймдев-индустрия Нидерландов: именно эта страна стала первой в Европе, сделавшей гейм-дизайн учебной дисциплиной.

Замыкают десятку турецкий и корейский языки. Эти страны в последние годы особенно интересуют разработчиков игр. Ведь среди стран Среднего Востока и Северной Африки именно Турция приносит гейм-девелоперам наибольший доход, а корейский игровой рынок четвёртый по доходности в мире.

По нашим наблюдениям, локализация на корейский уже многие годы пользуется стабильным спросом. А турецкий в последние несколько лет становится всё более популярным именно среди гейм-девелоперов.

А что за пределами топ-10?

Вторую десятку рейтинга открывают переводы с английского на польский язык. Количество заказов по этому языковому направлению совсем немного отстаёт от пары английский корейский.

Интересно, что переводы с английского на русский, на котором говорят около 260 млн человек в мире, популярны меньше переводов на польский, общее число говорящих на котором около 40 млн. И это далеко не единичный случай, когда количество говорящих и популярность языка для перевода не коррелируют друг с другом. Рассмотрим эту особенность подробнее.

Влияет ли общая численность говорящих на популярность языка для локализации?

По нашим наблюдениям скорее нет, чем да. Выше мы уже привели пример с польским и русским. Ещё пример: общее число говорящих на японском около 140 млн (сравните с 260 млн русскоговорящих). Но переводы с английского на русский занимают в нашем рейтинге лишь 12-е место, а на японский 6-е.

Ещё один пример. Говорящих на нидерландском в десятки раз меньше, чем владеющих упрощённым китайским. Но этот разрыв практически не отражается на популярности обоих языков для локализации с английского. Они занимают в нашем рейтинге седьмое и восьмое места соответственно, причём с очень небольшим отрывом друг от друга.

Такую же тенденцию мы заметили и за пределами топа. Например, общее число говорящих на вьетнамском около 90 млн человек; индонезийский язык распространён в 2,2 раза больше, а хинди почти в 7 раз. Тем не менее, количество заказов по переводу с английского на каждый из этих языков было у нас в 2020-м почти одинаковым.

Продолжая анализировать азиатские страны, похожую картину увидим и с языками Малайзии и Таиланда. Локализация на тайский интересует наших клиентов почти вдвое чаще переводов на малайский и это несмотря на то, что на тайском говорит в 4 раза меньше людей на Земле, чем на малайском.

Что принимать во внимание при выборе языка для локализации?

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

Для принятия решения не помешают и данные об активности конкурентов и популярности онлайн-платежей в заинтересовавшей вас стране. А для выстраивания правильной стратегии продвижения нужно выбрать цель: качество пользователей или их количество.

С чего начать локализацию игры или приложения? Конечно, это зависит от бюджета. Наши клиенты, как правило, начинают с локализации интерфейса продукта, параллельно с этим переводя справочную документацию и сайт. Для мобильных приложений вместе с UI локализуют описания и скриншоты для сторов. А если проводятся локальные маркетинговые кампании, переводится и рекламный контент: текстовые объявления, баннеры, видеоролики.

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

На какой бы стадии выпуска продукта на новый рынок вы ни находились, обращайтесь за локализацией к нам в Alconost. Мы переводим сервисы, сайты, игры и приложения на 70+ языков.

Больше статистики по локальным рынкам

Как мы упоминали в начале, языки из топ-12 это только 2/3 локализаций. О менее популярных, но не менее интересных направлениях для локализации с английского мы решили рассказать в дополнительной подборке. Из неё можно можно узнать:

  • какой из языков Северной Европы был самым популярным среди наших клиентов в 2020-м, а какой заметно отставал от тройки лидеров;

  • какие языки Центральной Европы, помимо входящего в топ польского, были востребованы для локализации приложений, игр и сервисов с английского;

  • на какие языки Южной Европы стоит обратить внимание помимо испанского, итальянского и турецкого, входящих в топ-10;

  • как обстоят дела с локализацией на языки стран Ближнего Востока.

Посмотреть эту подборку можно в нашем блоге.

Обзоры рынков конкретных стран и рекомендации по локализации для них от Alconost

  1. Чехия и Словакия

  2. Финляндия

  3. Япония

  4. Арабский рынок

  5. Бразилия

  6. Япония, Корея, Китай

  7. Канада

Подробнее..

Интерактивные финансовые данные в 20 строках кода

25.06.2020 10:15:49 | Автор: admin
Статьи на финансовые темы появляются на Хабре регулярно. Во многих из них в качестве источника первичных данных используется неофициально открытое API Yahoo finance. В этой статье я покажу три способа добыть данные (включая Yahoo) а также как напилить из них простое вэб-приложение в 20 строк и выдать его клиенту, не умеющему в CLI.





Ванильный Yahoo

Итак, начнем с получения данных. Классический путь в этом случае API Yahoo. Недостатком является что это API не публичное, и по словам пользующихся людей постоянно что-то меняется и будет отваливаться. Боль на эту тему можно найти, например, там. Если нас такое не страшит то вперед, навстречу приключениям.
Обширная статья с описанием yahoo finance API недавно была на Хабре, есть где разгуляться
тем, кто любит Node.js. Мы же будем теребить питона, поэтому чтобы упростить себе жизнь вместо прямого обращения к API используем библиотеку yfinance. Будем надеяться, что перемены в исходном API будут отслежены создателями библиотеки, а нам останется только поддерживать актуальность используемой версии. Помимо упрощения жизни это допущение грозит в один прекрасный день превратить ваше приложение в неработающий кирпич, поэтому для долгосрочной перспективы я бы смотрел на два варианта обсуждаемых позже в статье.

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

Возьмем данные американской комиссии по ценным бумагам для сопоставлеия имен и тикеров. JSON можно стащить с их сайта. Я воспользовался удобной csv-шкой добытой в другом месте основанной на тех же данных. Ахтунг, в подобых списках могут быть компании снятые с торгов, поэтому рекоммендуются дополнительные проверки.
Например, в скачанном листе есть произодитель оборудования для полупроводниковой промышленности VSEA которую скупил AMAT и убрали с рынка лет 10 назад.

Для простоты создания интерфейса мы пилим его в стримлите. Это красиво и ОЧЕНЬ быстро в плане написания. Но если мы запихаем весь лист в 14 000 позиций в стримлитный селект бокс то интерфейс будет тормозить просто невероятно. Поэтому сделаем предварительную фильтрацию по вводу пользователя.

Если, например, ввести Microsoft то вас сразу перекинет в нужное, а если therapeutics то вас ждет лист с длинным скроллом, зато все просто летает по скорости. Готовый интерфейс незатейлив и прост, на все про все с импортом и проверками ушло 40 строчек. Если несколько упростить как в следующем примере, то выходит как раз 20, никакого кликбейта все честно.



Внутренности
import yfinance as yfimport streamlit as stimport pandas as pdfrom datetime import datetime# read SEC registered comaniessec_list = pd.read_csv('cik_ticker.csv', sep='|',                       names=['CIK', 'Ticker', 'Name', 'Exchange', 'SIC', 'Business', 'Incorporated', 'IRS'])name_options = ['Microsoft Corp']name_hint = st.sidebar.text_input(label='Company name contains')if name_hint is not None:    name_options = sec_list[sec_list['Name'].str.contains(name_hint, case=False)]['Name'].tolist()if not name_options:    name_options = ['Microsoft Corp']# get ticker from company name and dates from UIcompany_name = st.sidebar.selectbox('SEC listed companies', name_options)ticker = sec_list.loc[sec_list['Name'] == company_name, 'Ticker'].iloc[0]tickerData = yf.Ticker(ticker)end_date = st.sidebar.date_input('end date', value=datetime.now()).strftime("%Y-%m-%d")start_date = st.sidebar.date_input('start date', value=datetime(2010, 5, 31)).strftime("%Y-%m-%d")# make API queryticker_df = tickerData.history(period='1d', start=start_date, end=end_date)md_chart_1 = f"Price of **{ticker}** "md_chart_2 = f"Volume of **{ticker}** "if len(ticker_df) == 0:    tickerData = yf.Ticker('MSFT')    ticker_df = tickerData.history(period='1d', start=start_date, end=end_date)    md_chart_1 = f"Invalid ticker **{ticker}** showing **MSFT** price"    md_chart_2 = f"Invalid ticker **{ticker}** showing **MSFT** volume"# Add simple moving averageticker_df['sma 15'] = ticker_df.Close.rolling(window=15).mean()# plot graphsst.markdown(f"Demo app showing **Closing price** and **trade volume** of a selected ticker from Yahoo! finance API")st.markdown(md_chart_1)st.line_chart(ticker_df[['Close', 'sma 15']])st.markdown(md_chart_2)st.line_chart(ticker_df.Volume)



Иcxодники можно найти в репозитории, а поиграть с живым интерфейсом на heroku, ну если ничего не отвалится.

Альтернатива 1

Теперь рассмотрим альтернативы. Если нас не устраивает непубличный API Yahoo, которому сложно доверять в долгосрочном плане? Отличной алтернативой может быть API предлагаемое Quandl.

Этот вариант интерсен тем, что API официальное, платное только за премиум данные, и имеет интерфейсы на R и Python от самих же создателей. API очень щедрое для пользователей с бесплатным ключом, можно сделать 300 запросов за 10 секунд, 2000 за 10 минут и 50 000 в день. Аттракциона такой невиданной щедрости трудно найти в наши дни. Знакомьтесь- Quandl

Из недостатков некоторые довольно тривиальные данные вроде S&P 500 попали в премиальные. Пилим тот же нехитрый дашборд на 20 строк кода. Все так же просто. Для менее чем 50 запросов в день не нужен даже бесплатный ключ. Если запросов больше то надо регистрировать. Несколько упростив исходное приложение умещаемся в 20 строк (не забудьте вставить API key, бесплатно регистрируется там)

Чудеса компактности
import quandlimport streamlit as stfrom datetime import datetimequandl.ApiConfig.api_key = "YOUR_API_KEY"ticker = st.sidebar.text_input("Ticker", 'MSFT')end_date = st.sidebar.date_input('end date', value=datetime.now())start_date = st.sidebar.date_input('start date', value=datetime(2010, 5, 31))ticker_df = quandl.get("WIKI/" + ticker, start_date=start_date, end_date=end_date)ticker_df['sma 15'] = ticker_df.Close.rolling(window=15).mean()# plot graphsst.markdown(f"Demo app showing **Closing price** and **trade volume** of a selected ticker from Quandl API")st.markdown(f"Price of **{ticker}** ")st.line_chart(ticker_df[['Close', 'sma 15']])st.markdown(f"Volume of **{ticker}** ")st.line_chart(ticker_df['Volume'])






Далее можно повышать градус неадеквата анализа неограниченно, пандас вам в руки.
Например, добавить классические метрики вроде корреляции с рынком (за рынок берем S&P 500). Для пущей научности добавляем сравнение с безрисковым инструментом (трехмесячные трежерис) и вычисляем альфу, бету и соотношение Шарпа. Это мы будем делать на примере другого источника, где на бесплатной подписке ограничивают не доступность групп данных, а только число запросов (хотя quandl нам тоже пригодится, данные про трежерис мы возьмем именно там).

Альтернатива 2

Наш второй конкурсант Alpha Vantage. Alpha Vantage API предлагает дневные и внутридневные данные по фондовым рынкам, технические индикаторы в готовом виде, данные рынков валют и даже крипты. По внутридневным доступны интервалы до 1 минуты. Если вы не занимаетесь лотереей внутридневной торговлей и прочим скальпингом, то 500 запросов в день которые дает вам бесплатный ключ вам вполне хватит. Ну а если вы настоящий биржевой воротила, то премиум ключ стоит меньше чем масло в вашем Бентли поменять, о чем беспокоиться? Зарегистрировать бесплатный ключ можно там

Смена источника данных требует минимальной коррекции кода, потому что все варианты умеют выдавать пандасовские датафреймы. Покрытие рынков вполне достойное, американским не ограничивается, по тикерам вроде GAZP.ME, SBER.ME вполне можно следить за нашим посконным. Из недостатков для Питона вам все равно понадобится некоторый обвес для работы с API если не хотите писать его сами. Он есть, но источник его не связан с авторами API и документированность оставляет желать лучшего.

Кроме того, если начать теребить API часто, то выясняется что бесплатно 500 запросов в день и 5 в минуту (пролистайте вверх и сравните с цифрами quandl, про невиданную щедрость я писал вполне серьезно!). Так что для всякой мелочи типа изменения временного диапазона или постоянно запрашиваемого тикера (вроде S&P 500) рекомендуется воспользоваться кешированием в стримлите, чтоб не дергать API понапрасну. Помните, что стримлит без кеширования перезапускает скрипт целиком после взаимодействия пользователя с интерфейсом, даже если он просто поменял границы отображаемого временного отрезка уже скачанных данных. Запрос с параметром outputsize='full' выдает всю историю за 20 лет, фильтрование по датам делаем уже на своей стороне, тоже помогает снизить число обращений.
Главное отличие от предыдущих случаев будет в том, что обращение к API теперь надо обернуть в функцию и навесить на нее кеширующий декоратор

@st.cache(suppress_st_warning=True, allow_output_mutation=True)def get_ticker_daily(ticker_input):    ticker_data, ticker_metadata = ts.get_daily(symbol=ticker_input, outputsize='full')    return ticker_data, ticker_metadata


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


Потроха нехитрой аналитики
import streamlit as stfrom alpha_vantage.timeseries import TimeSeriesfrom datetime import datetimeimport quandlimport pandas as pdquandl.ApiConfig.api_key = "YOUR_QUANDL_API_KEY"ts = TimeSeries(key='YOUR_ALPHA_VANTAGE_API_KEY', output_format='pandas')st.markdown(f"Demo app showing **Closing price** and  daily **APR change** of a selected ticker from alpha vantage API")ticker = st.sidebar.text_input("Ticker", 'MSFT').upper()end_date = st.sidebar.date_input('end date', value=datetime.now()).strftime("%Y-%m-%d")start_date = st.sidebar.date_input('start date', value=datetime(2015, 5, 31)).strftime("%Y-%m-%d")@st.cache(suppress_st_warning=True, allow_output_mutation=True)def get_ticker_daily(ticker_input):    ticker_data, ticker_metadata = ts.get_daily(symbol=ticker_input, outputsize='full')    return ticker_data, ticker_metadatatry:    price_data, price_meta_data = get_ticker_daily(ticker)    market_data, market_meta_data = get_ticker_daily('SPY')    md_chart_1 = f"Price of **{ticker}** "    md_chart_2 = f"APR daily change of **{ticker}** "except:    price_data, price_meta_data = get_ticker_daily('MSFT')    market_data, market_meta_data = get_ticker_daily('SPY')    md_chart_1 = f"Invalid ticker **{ticker}** showing **MSFT** price"    md_chart_2 = f"Invalid ticker **{ticker}** showing **MSFT** APR daily change of"def apr_change(pandas_series_input):    return ((pandas_series_input - pandas_series_input.shift(periods=-1,                                                             fill_value=0)) / pandas_series_input) * 100 * 252price_data['change'] = apr_change(price_data['4. close'])market_data['change'] = apr_change(market_data['4. close'])price_data_filtered = price_data[end_date:start_date]market_data_filtered = market_data[end_date:start_date]stock_market_correlation = price_data_filtered['change'].corr(market_data_filtered['change'], method='pearson')# estimate risk free return via 3 months treasury bondstreasury_yield = quandl.get("FRED/TB3MS", start_date=start_date, end_date=end_date)rfr = treasury_yield['Value'].mean()  # mean treasury yield over periodstock_volatility = price_data_filtered['change'].std()market_volatilidy = market_data_filtered['change'].std()stock_excess_return = price_data_filtered['change'].mean() - rfrmarket_excess_return = market_data_filtered['change'].mean() - rfrbeta = stock_market_correlation * stock_volatility / market_volatilidyalpha = stock_excess_return - beta * market_excess_returnsharpe = stock_excess_return / stock_volatilitymetrics_df = pd.DataFrame(    data={'mkt correlation': [stock_market_correlation], 'alpha': [alpha], 'beta': [beta], 'Sharpe ratio': [sharpe]})metrics_df.index = [ticker]st.markdown(md_chart_1)st.line_chart(price_data_filtered['4. close'])st.markdown(md_chart_2)st.line_chart(price_data_filtered['change'])st.table(metrics_df)




Судя по хорошей корреляции индекса с самим собой и нулевой альфе грубой лажи удалось избежать. На всякий случай напомнбю альфа это превышение доходности инструмента над рынком, здесь и далее в процентах в годовом исчислении. Чем положительнее и больше тем бодрее растет акция по сравнению с рынком. Интервал сравнения для всех с 1 января 2010 года. Можно видеть на примере последних 10 лет, что Майкрософт (MSFT) растет не сильно выше рынка,



а вот Фейсбук (FB) или Амазон (AMZN) все еще существенно обгоняют.





Можно также убедиться, что, например, частные тюрьмы и прочий коммерческий ГУЛАГ (CXW, GEO)





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

Доставка streamlit аппа на дом

Переходим к последней части. Доставка конечного продукта пользователю, который сидит далеко за фаерволом, а публикация на открытом хостинге не вариант. Ну, например, вы сходили на тренинг по успешному успеху и теперь выдаете этот дашборд как часть пакета начинающего инвестора тем, кто прошел ваш вебинар за 199 000 руб (ходят слухи, что это разрушает карму и в следующих перерождениях такие люди становятся туалетными ершиками). Итак, пакуем продукт для доставки.

Просим пользователя установить ContainDS и Докера. Ставим себе. Запускаем базовый стримлит образ, указав папку с нашим поделием, кликнув на CMD доставляем нужные зависимости из requirements.txt. И наконец экспортируем все это добро в один *.containds файл. Сохраняем и шлем клиенту (не по емейлу конечно, наш образ весит без малого 600 мегабайт)



От клиента требуется загрузить файл и мышкой кликнуть на WEB. Никаких хакерных консолей, можно научить хоть тетенек в бухгалтерии. Будете потом гордиться, что у вас тетеньки в бухгалтерии гоняют сервисы в докерных контейнерах. Пошаговая инструкция.

Бонус

Ну и наконец для тех чтитателей или их клиентов, кто заинтересовался данными, но считает все эти докеры с жаваскриптами поверх питонов излишними свистелками и перделками. Для акул старой школы эксельный плагин для импорта данных из alpha vantage. Аналогичное для Quandl. Всем кто недавно ностальгировал в юбилейной трибьют-теме чуваки, про вас помнят!

Для фанатов винтажного на новый лад с маффинами, смузи и митболами есть вариант с гугловскими таблицами, и зиро кодинг и модное облако

Из моего короткого знакомства с тремя API мне показалось, что в целом самый щедрый это Quandl, особенно для платных клиентов. Если запросов мало, а платность не вариант то alpha vantage сгодится тоже. С yahoo настораживает вопрос кто же платит за угощение для всех, не исчезнет ли оно в один прекрасный день. Много примеров работы с Quandl и аналитики вообще можно найти во втором издании Mastering Python for Finance (есть на Либрусеке). Делитесь своими находками в области, в комментах статьи про yahoo finance API писали про Тинькова и другие варианты, но без подробностей

Фото на обложке поста Photo by M. B. M. on Unsplash
Подробнее..

Программное формирование мультисессии Adobe Audition с аудиозаписями телефонных звонков

26.07.2020 18:18:25 | Автор: admin
В предыдущей статье я писал про формирование векторной графики SVG с диаграммой телефонных звонков, напоминающей диаграмму Ганта. Информацию о телефонных звонках я брал из детализации, которую скачивал через личный кабинет на сайте мобильного оператора. Дело было почти четыре года назад. В настоящее время у меня появилась идея сделать проект посложнее: построить мультисессию в звуковом редакторе Adobe Audition 1.5 из аудиозаписей телефонных разговоров. При этом эти аудиозаписи расположить в мультисессии строго в соответствии по времени, а так же по датам, которым будут соответствовать треки. При этом визуально такая мультисессия будет напоминать ту же диаграмму, что и строилась в предыдущей статье. Кроме того, будет возможность оперативного масштабирования и прослушивания записей телефонных разговоров, как в миксе, так и в режиме соло по дням.

Мультисессию я решил строить из аудиозаписей, накопленных за один календарный месяц во избежание лишних нагромождений для Adobe Audition. Вручную такую сессию, конечно же, построить можно, но это долгая и кропотливая работа. Главный интерес данной задачи автоматизировать построение мультисессии программными средствами. А точнее, написать программу, которая на основе списка файлов аудиозаписей сформирует файл SES мультисессии Adobe Audition. Для тех, кто не в курсе: мультисессия, кратко говоря, это проект, состоящий из множества различных аудиозаписей, распределённых во времени и по трекам (дорожкам) и предназначенный для создания микса из них.

Прежде всего, стоит оговорить, каким образом я получаю файлы аудиозаписей телефонных разговоров. Ни для кого не секрет, что современные смартфоны обладают возможностью записывать телефонные звонки различными инструментами, как встроенными в систему, так и сторонними. Лично я пользуюсь планшетом Lenovo TAB3 (на процессоре MT8735P). Аппарат позволяет совершать аудиозаписи в ручном режиме в сжатом формате, получая на выходе файлы с расширением 3gpp. Записи получаются стереофоническими с разделёнными каналами: в одном канале пишется голос абонента, а в другом свой голос. Сжатый формат аудиозаписей сказывается на их искажении при воспроизведении. В связи с этим я пользуюсь сторонними приложениями для аудиозаписи, которых существует бесчисленное множество. Одно из приложений, которое мне понравилось больше всего Record My Call. Данное приложение записывает звонки в автоматическом режиме, имеет множество настроек, связанных, в частности, с выбором формата и качества аудиозаписи. А также, в качестве бонуса, приложение имеет неплохой очень удобный встроенный журнал звонков, который сохраняется в файл базы данных db (рис. 1).


Рис. 1. Журнал звонков в приложении Record My Call.

Самые лучшие для качества звучания параметры аудиозаписи WAV 8000Hz 16bit Stereo. При таких настройках запись не имеет искажений, звучит чётко, хоть и занимает в памяти больше места. Приложение настроено таким образом, чтобы аудиозапись начиналась автоматически ещё до начала телефонного разговора: при поступлении входящего вызова до снятия трубки или при начале набора номера во время гудков. То есть, пропущенные и неотвеченные вызовы также записываются. Можно настроить так, чтобы записывался только разговор. Формат имени файла аудиозаписи также настраивается. В своём случае я настроил так, как показано на рисунке 2.


Рис. 2. Настройка формата имени файла в Record My Call.

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

Прежде чем браться за формирование файла SES мультисессии, нужно разобраться, как такой файл устроен. Документации по данному формату, разумеется, нигде нет, поэтому мне пришлось разгадывать собственными силами, опираясь на личный опыт и знания. Данный файл не является текстовым, поэтому в Блокноте его открывать толку мало. На помощь приходит WinHex шестнадцатеричный редактор. Я уже писал ряд статей по работе с двоичными данными и расшифровке информации, в частности, статья о написании программы перепаковки видео 264-avi. Там я более-менее подробно написал об устройстве файла формата avi.

Сначала я создал простую произвольную мультисессиию в Adobe Audition 1.5, состоящую из одного трека и одного аудиофайла (рис. 3), сохранив её в файл с расширением ses. Файл получился размером 2422 байта. Затем данный файл я открыл в WinHex (рис. 4).


Рис. 3. Вид мультисессии в Adobe Audition 1.5 Пример 1.


Рис. 4. Файл мультисессии, открытый в WinHex.

На первый взгляд вообще ничего не понятно. В символьной части окна можно увидеть смысловые слова COOLNESS, hdr, Мастер. Если полистать документ ниже, можно увидеть текст, содержащий полный путь к файлу (причём, в двух вариантах), который используется в мультисессии. Это показано на рисунке 5 и обведено зелёным цветом. Сразу же бросаются в глаза короткие смысловые слова, обведённые на том же рисунке в красную рамку.


Рис. 5. Байты путей к аудиофайлам мультисессии.

Просматривая более внимательно данный документ от начала до конца, я заметил ещё несколько других коротких смысловых слов. Так же я заметил, что длина любого смыслового слова кратна четырём. Видимо, эти слова являются заголовками блоков, из которых состоит весь файл мультисессии. Мне это напомнило RIFF-структуру avi или wav файла, состоящего из блоков, в которых также есть заголовки таких же размеров. После таких заголовков там следовало 32-битное число (4 байта), обозначающее размер текущего блока. Принимая этот факт во внимание, я решил проверить, работает ли этот принцип для файла ses? Оказалось, что в случае с форматом ses это так же прокатывает (рис. 6).


Рис. 6. Схожесть с RIFF структурой (на примере блока WLST).

Первое слово COOLNESS в файле ses, видимо, служит главным заголовком и признаком типа данного файла. Следующие 4 байта размер содержимого, что размещено далее, вплоть до конца файла. То есть, если внимательно посчитать, это значение на 12 байт меньше, чем размер всего файла. А дальнейшее содержимое состоит из совокупности различных блоков. Блок имеет заголовок из четырёх или восьми байт, затем следует 4 байта, обозначающие размер данного блока, а уже после них следует содержимое данного блока. У некоторых блоков я выявил наличие субблоков, но об этом будет сказано по ходу более подробного описания каждого блока. В данном файле, что в примере, я насчитал 17 блоков, они перечислены в таблице на рисунке 7.


Рис. 7. Список блоков, входящих в состав мультисессии.

Как видно из таблицы, некоторая одна и та же информация представлена в разных вариантах разными блоками. Наверно это сделано для совместимости различных версий программы. Забегая вперёд, зелёным цветом выделены те блоки, без которых представленная в примере мультисессия существовать не может. Серым цветом выделены два блока, размером 4 байта, которые в данной сессии присутствуют фиктивно. Действительно, у меня стал вопрос: а что будет, если выкинуть часть блоков из файла? Ведь мне, к примеру, не нужна информация о метрономе и темпе, и огибающие на клипах (точнее, на одном клипе) в моём простом примере отсутствуют. Огибающие это кривые поверх аудиоклипа, задающие динамику параметров звучания (громкость, баланс) во времени. Я последовательно начал вырезать блоки из данного файла, не забывая пересчитывать и корректировать значение после слова COOLNESS. В итоге мультисессия успешно открывалась при наличии как минимум пяти блоков, выделенных зелёным цветом. В сессии присутствуют два блока списка аудиофайлов. Можно было оставить любой из них. Мне больше симпатичен второй вариант (блок LISTFILE), так как в первом варианте (блок WLST) в описании пути к файлу приходится по два байта на символ. Возможно, это сделано для расширенного алфавита символов, но мне достаточно стандартного алфавита ASCII. Тем более, русские символы, как видно, отлично поддерживаются. Описание аудиоклипов представлено в трёх вариантах. Я выбрал первый вариант (блок bk20), потому что в его описании я разобрался быстрее всего.

Мультисессия из аудиозаписей телефонных разговоров по своей сложности будет схожей с мультисессией, представленной в данном примере. Единственное отличие она будет объёмнее: число аудиофайлов будет достаточно большим, а число треков будет равняться числу дней в месяце. Для такой мультисессии другие какие-либо навороты не нужны. Размеры блоков hdr и stat статичны и всегда составляют 936 и 40 байт соответственно, независимо от размера мультисессии. Размеры блоков trks и bk20 зависят от количества треков и аудиоклипов в мультисессии соответственно. А вот размер блока LISTFILE самый непредсказуемый: он зависит не только от количества аудиофайлов в мультисессии, но и от длины их имён и путей их расположения.

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

В содержимом блока заголовка мультисессии hdr (в конце именно пробел) ключевыми байтами являются первые 12 байт, то есть, 3 слова по 4 байта (рис. 8). Первое слово частота дискретизации семплов в мультисессии. Для моей мультисессии это значение составляет 8000 Гц (0x1F40). На рисунке 8 оно выделено зелёной заливкой. Напомню, что байты в словах для числовых значений читаются задом наперёд. Второе слово продолжительность (длина) мультисессии, выраженная в количестве семплов (оранжевая заливка на рисунке). В рассматриваемом примере это значение составляет 0x1A365E (1717854). Если перевести в минуты, то получится 1717854/8000/60, что составляет примерно три с половиной минуты. Так оно и есть: при минимальном масштабе мультисессия имеет именно такую продолжительность. А для мультисессии из записей телефонных вызовов продолжительность должна составлять сутки, или 24*3600*8000 = 691200000 = 0x2932E000 семплов. При таком раскладе, кстати сказать, текущее время воспроизведения мультисессии на панели внизу, являющееся относительным временем, будет в точности совпадать со значением абсолютного времени текущего телефонного звонка (или группы звонков по дням). Следующее слово, выделенное жёлтой заливкой, обозначает количество аудиоклипов в мультисессии. В примере это значение равняется единице, но в случае с телефонными звонками число таких клипов будет равняться числу аудиофайлов. Забегая вперёд, последнее сказанное не совсем корректно. На самом деле число аудиоклипов может быть чуть больше, чем число аудиофайлов. На один файл может прийтись два клипа в том случае, если наступили новые сутки во время телефонного разговора. В таком случае придётся делать перенос записи на новый трек, и одним клипом обойтись не получится. Но такие случаи на практике встречаются редко, так как переход на новые сутки приходится на ночное время, когда активность телефонных звонков минимальна. Кстати, этот момент я не стал учитывать при формировании SVG диаграммы в предыдущей статье. После слова значения количества блоков следует, вероятнее всего полуслово из двух байт 0x0020, или 32 в десятичном виде. Его тоже можно было выделить цветной заливкой, так как, скорее всего, оно означает разрядность микширования. В Adobe Audition в статусной строке внизу указано: 8000 Гц, 32-битное микширование. Кроме трёх самых необходимых слов содержимого hdr присутствуют другие непонятные байты. К примеру, слово Мастер я даже не знаю, к чему относится. Видимо, это название главной шины микширования. Но самые интересные группы байт я обвёл в серую рамку. Дело в том, что именно такая последовательность часто встречается и в других блоках файла мультисессии. Я не случайно объединил в группу именно 8 байт, так как, скорее всего, это вещественный тип данных. В частности, данная константа 00 00 00 00 00 00 F0 3F HEX редактором в типе Double интерпретируется как 1.0e+0, то есть, как единица. Скорее всего это значения уровней громкости и прочих крутилок, но заданные не в децибелах, а в виде коэффициета. Сразу скажу, что все байты любого блока, которые мне не удалось распознать (или не было в этом необходимости) будут записываться в формируемый файл мультисессии без изменений, как в примере.


Рис. 8. Часть байтов блока заголовка hdr .

Блок stat текущего состояния мультисессии (самый короткий) я решил не изучать. Я создал другую образцовую мультисессию из одного аудиофайла, растянул её на продолжительность в 24 часа и сделал её полный вид (масштаб) по горизонтали. А по вертикали вид треков отмасштабировал так, чтобы при развёрнутом окне Adobe Audition на FullHD экране помещался 31 трек. Это максимальное число дней в одном месяце. Курсор мультисессии расположил в самом начале. Затем я сохранил данную мультисессию в другой файл, после чего вытащил оттуда блок stat со всеми его заголовками. Эти байты я сохранил в файл stat_31_full.BLK для дальнейшего использования при разработке программы. Вид содержимого такого файла представлен на рисунке 9. Размер данного файла составил 48 байт (40 байт содержимого блока + 4 байта заголовка + 4 байта описания размера содержимого).


Рис. 9. Байты блока состояния stat для моей мультисессии.

Для более наглядного описания следующих трёх блоков по ходу написания данной статьи я решил создать мультисессию посложнее, состоящую из двух треков, двух файлов и трёх клипов (рис. 10). Первый файл Incoming_Call 20200622_124844 +74999545237.wav имеет длительность 281280 семплов. Второй файл Outgoing_Call 20200621_231753 +79536170218.wav имеет длительность 63360 семплов. Первый трек с именем Первый (переименовал) содержит два клипа. Первый клип смещён от начала сессии на 10 секунд (на 80000 семплов). Клип представлен полным содержимым первого аудиофайла, то есть, длительность клипа совпадает с длительностью файла. Второй клип смещён на 50 секунд от начала сессии (на 50*8000=400000 семплов). Клип представлен неполным содержимым второго аудиофайла. Внутри данного клипа аудио начинается от начала файла, но длится только 5 секунд (40000 семплов). То есть, длина клипа составляет 5 секунд. Второй трек с именем Второй содержит один клип. Он смещён от начала сессии на одну секунду (на 8000 семплов). Данный клип представлен неполным содержимым первого аудиофайла. Внутри данного клипа аудио начинается не от начала, а спустя 3 секунды, но содержит его до самого конца. Таким образом, смещение аудиоданных внутри этого клипа составляет 3 секунды (24000 семплов). А длина данного клипа вычисляется, как разность между длительностью соответствующего аудио и смещением аудиоданных внутри клипа. В данном случае длина клипа равняется 281280-24000 = 257280 семплам.


Рис. 10. Вид мультисессии в Adobe Audition 1.5 Пример 2.

На рисунке 11 представлен вид содержимого блока описания треков trks. В красную рамку выделены 4 байта заголовка блока, в зелёную размер содержимого блока. Об этом уже говорилось выше. Далее идёт содержимое блока, байты которого выделены в редакторе WinHex характерной голубоватой заливкой. Размер выделения, значение которого отображается в нижнем правом углу редактора (также обведено в зелёную рамку), совпадает со значением из байтов после заголовка и уже в данном примере составляет 308 байт. Если в первом (предыдущем) примере из одного трека размер блока составлял 156 байт, а в текущем 308 байт, то можно сделать следующий вывод. Ввиду предположения об однородности и равнозначности треков, области описания каждого трека должны иметь одинаковый размер. Данные области, можно так сказать, являются субблоками блока trks. На рисунке они обведены в синюю рамку. Выяснилось, что размер одного такого субблока составляет 152 байта. А в самом начале идущих подряд субблоков стоит подзаголовок из четырёх байт, отмеченных на рисунке жёлтой заливкой. Эти четыре байта есть ничто иное, как значение количества треков в мультисессии, или количества субблоков. И так, размер S содержимого блока trks можно вычислить по формуле S=4+152*n, где n число треков в сессии. Так оно и есть: 4+152*1=156, а 4+152*2=308.


Рис. 11. Байты блока описания треков trks.

Теперь перейдём к описанию содержимого субблока. Там есть много чего, но я расшифровал только самое необходимое. Это всего-навсего три параметра: 4 байта двоичных флагов (обведено красным), имя трека (обведено коричневым) и идентификатор трека (обведено голубым). Идентификатором трека является его порядковый номер. Он нужен для указания ссылки на трек в описании аудиоклипов (позже об этом будет сказано). Имя трека занимает область в 36 байт. Это максимальное число символов в имени трека, но оно может быть и меньше, как в текущем примере. Незадействованные байты при этом нулевые. В мультисессии с аудиозаписями телефонных звонков имена треков будут совпадать с записью соответствующих дат. Можно приписать рядом с датой соответствующий ей день недели двумя заглавными буквами в сокращённом виде. Четыре байта двоичных флагов (всего 32 флага) предназначены для описания двоичных параметров, свойственных треку. На самом деле их может быть меньше, чем 32. Я расшифровал только часть флагов. Из них как минимум три флага указывают, активирован ли на треке параметр R (Record), S (Solo) или M (Mute). В указанном примере ни одна из этих трёх кнопочек на треках не нажата, а значение двоичных флагов равно нулю (0x00000000). Но если нажать на треке кнопочку R (то есть, поставить трек на запись) и заново сохранить сессию, то значение двоичных флагов станет равно 0x00000004, иначе говоря, третий по счёту бит справа (bit2) станет единичным. Именно этот бит и отвечает за свойство трека запись. Данное свойство в моём проекте не имеет никакого значения, так как моя мультисессия рассчитана на визуальный просмотр и воспроизведение. Однако у меня появилась идея, чтобы кнопочка R была нажата на тех треках, которые соответствуют выходным дням. Этот приём позволит удобнее визуализировать мультисессию.

Блок списка аудиофайлов мультисессии LISTFILE (рис. 12) состоит из следующих частей. Как и в случае с блоком описания треков его также можно разделить на субблоки по количеству файлов в сессии. По аналогии с рисунком 11, я также выделил в красную рамку восьмибайтный заголовок блока, а в зелёную рамку размер его содержимого. В данном конкретном примере это значение составляет 188 байт. Содержимое выделено по аналогии с рис. 11. Оно разбито на две зоны, выделенные синей линией. Это и есть субблоки блока списка файлов.


Рис. 12. Байты блока описания аудиофайлов LISTFILE.

Каждый субблок соответствует одному аудиофайлу. В примере используется два аудиофайла, поэтому количество субблоков соответствующее. В отличие от предыдущего случая с описанием треков здесь отсутствует подзаголовок о числе субблоков. В состав субблока входят 4 байта его заголовка wav (выделено в чёрную рамку) и 4 байта, указывающие размер дальнейшего содержимого (выделено в пурпурную рамку). Для обоих субблоков это значение в данном примере одинаковое и составляет 0x56 (86) байт. Это связано с тем, что файлы располагаются по одинаковому пути и имеют имена одинаковой длины. Точнее говоря, полные имена файлов имеют одинаковое число символов. В противном случае субблоки имели бы разный размер. Область содержимого субблока (дальнейшие байты) содержит следующую информацию. В голубую рамку выделено число, являющееся идентификатором аудиофайла. В отличие от идентификатора трека, данное число не является порядковым номером файла. Как я понял, при сохранении мультисессии оно назначается случайно или псевдослучайно для каждого файла. Главное, чтобы не было совпадения среди этих значений. В этом я убедился, когда сохранил мультисессию дважды и сравнил файлы ses по содержимому. В результате оказалось, что файлы отличаются как раз на эти самые байты. И не только на эти. Случайный номер назначается также идентификатору слоёв огибающих в блоке ep20. Но в этом блоке, как уже говорилось выше, необходимость напрочь отсутствует, и рассматриваться его описание в этой статье не будет. Идентификаторы аудиофайлов нужны для их связки с клипами. Данная связка происходит в блоке с описанием клипов. В своём случае для мультисессии с записями телефонных разговоров идентификаторы для аудиофайлов будут представлять собой последовательность натуральных чисел, но начиная не с нуля, а, например, с 1000. Следующие 4 байта, которые я не выделил, в обоих субблоках имеют значение 0x13. Вероятнее всего, этим значением указывается тип формата аудиофайла. Можно условно считать это значение константой, так как все аудиофайлы у меня однотипные. Следующая цепочка байт описывает полное имя аудиофайла с завершающим нулевым байтом (типа признак конца строки). Размер этой цепочки на единицу больше, чем число символов в полном имени аудиофайла. Далее идёт константа 0xFFFFFFFF. После неё следует значение, обозначающее число семплов в данном аудиофайле (на рис. 12 выделено в жёлтую рамку). Для первого файла это значение равняется 0x44AC0, а для второго 0xF780. Они как раз соответствуют десятичным значениям 281280 и 63360 соответственно, которые уже фигурировали выше в описании второго примера мультисессии.

Наконец, осталось рассмотреть описание самого сложного блока блока описания аудиоклипов bk20 (рис. 13). По аналогии с предыдущими двумя рисунками выделены заголовок и размер содержимого блока.


Рис. 13. Байты блока описания аудиоклипов bk20.

В содержимом блока в первую очередь стоят два подзаголовка по 4 байта каждый. Они выделены пурпурной и голубой заливкой. Первый подзаголовок число клипов в сессии. В примере их три. Второй подзаголовок константа 0x48 (72). Видимо она обозначает размер каждого субблока, а они как раз идут далее. Их число совпадает с числом клипов в сессии. Каждый такой субблок описывает параметры одного клипа. Кстати, размер D содержимого блока bk20, получается, можно рассчитать по формуле D=8+72*b, где b количество аудиоклипов в мультисессии. На рисунке отсутствуют поясняющие выделения байт внутри субблоков, так как необходимых параметров получилось достаточно много. Они вынесены в отдельную таблицу (рис. 14). Голубой заливкой выделены те параметры, которые необходимы в моём проекте, а серой заливкой неопознанные константы. Также в этой таблице представлены значения параметров для каждого из трёх клипов мультисессии из последнего примера.


Рис. 14. Список параметров субблока описания аудиоклипа.

Первое слово (группа из 4-х байт) ссылка на огибающую, которая нам не нужна. Второй параметр ссылка на аудиофайл. Значение данного параметра равняется значению идентификатора того аудиофайла, которому соответствует данный аудиоклип. Потом идут две вещественные константы, которые уже фигурировали ранее. После них идут три координирующих параметра, выраженные в числе семплов: смещение клипа от начала сессии, длина (продолжительность) клипа в сессии и смещение аудио внутри клипа. Из названия данных параметров всё должно быть ясно. Чуть ранее при подробном описании второго примера мультисессии я указывал числовые значения всех смещений и продолжительностей. На рисунке 14 в таблице параметры для каждого клипа указаны в шестнадцатеричной форме. Эти значения в таблицу я заносил, переписывая их непосредственно из рисунка 13. Но если преобразовать их в десятичную форму, то они совпадут с соответствующими значениями из описания второго примера (проверял отдельно). Стоит обратить внимание, что ссылки на аудиофайл у первого и третьего клипов имею одно и то же значение 0x3F5B050, так как оба клипа ссылаются на один и тот же аудиофайл с соответствующим идентификатором. Затем следует блок байтов двоичных параметров (4 байта). Как и в случае с описанием треков, я расшифровал только часть битов. Значение по умолчанию составляет 0x00080000, то есть, если перевести в двоичную систему, то только один bit19 поднят в единицу, а остальные 31 битов равны нулю. Без данного единичного бита, как показала практика, мультисессия загружаться отказывается. В текущем примере такое значение свойственно первому и второму клипу, а вот у третьего почему-то значение флагов равняется 0x000A0000. Если посчитать, то в этом значении подняты два бита: по-прежнему bit19 и ещё bit17. Не знаю, почему так получилось. Я попробовал сбросить bit17 в ноль, изменив значение всего параметра на 0x00080000, как у соседних клипов. В результате сессия в Adobe Audition открылась без видимых каких-либо изменений. При работе в Adobe Audition я обратил внимание на такие свойства клипов, как Фиксировать во времени и Фиксировать только для воспроизведения. Логично предположить, что за сохранение данных свойств отвечают какие-то определённые биты в блоке двоичных параметров. Есть там ещё и другие двоичные свойства у клипов, но они нам не требуются. А перечисленные два свойства будут весьма полезны. Свойство Фиксировать во времени полезно тем, что клип будет защищён от возможности случайного сдвига указателем мыши в горизонтальном направлении. Но на таком клипе визуально в левом нижнем углу будет нарисован символ в виде замка в кружочке, а это лишняя для просмотра графическая информация. Второе свойство клипа Фиксировать только для воспроизведения полезно тем, что при активированном на соответствующем треке параметре R (Record) клип не приобретёт принудительную красную окраску. Для чего я решил использовать на некоторых треках параметр R написано выше. Опытным путём я вычислил, что за первое свойство клипа отвечает bit1, а за второе bit3. Из всего сказанного следует следующее. Чтобы присвоить клипу свойство Фиксировать во времени, нужно записать в двоичные параметры значение 0x00080002. Для свойства Фиксировать только для воспроизведения 0x00080008. Для обоих свойств их логическую сумму 0x0008000A. С двоичными параметрами разобрались. После этих байтов прописана ссылка на трек, на котором стоит клип. По сути дела прописан идентификатор трека, совпадающий с его порядковым номером. Программа Adobe Audition 1.5, кстати говоря, поддерживает не более 128 треков, поэтому такой идентификатор вписывается в один байт, хотя и числится 32-разрядным значением. Затем идут нерасшифрованные нулевые константы (4 константы по 4 байта каждая). Наконец, последний значимый параметр цвет клипа. Редактор Adobe Audition 1.5 позволяет в соответствующем диалоговом окне выставить клипу значение цвета от 0 до 239 или выбрать его из палитры (рис. 15). Цветовая палитра особо не радует, но другие варианты не даны. Цвет клипа по умолчанию 102 (0x66) (зелёненький).


Рис. 15. Диалоговое окно выбора цвета аудиоклипа в Adobe Audition 1.5.

Параметр цвета в файле ses 32-разрядный, а цветов по факту всего 240, что помещается в один байт. Остальные три старших байта нулевые. У меня была мысль, что если попробовать отредактировать эти байты на другие значения, то при открытии мультисессии на клипе появятся новые цвета. Но этот фокус не сработал. Как было сказано в предыдущей статье, цвета на диаграмме полезны для визуального выделения того или иного свойства телефонного вызова. Мультисессия из аудиозаписей телефонных вызовов будет напоминать подобную диаграмму, поэтому цвет клипов очень даже будет как нельзя кстати. После параметра цвета клипа идут два слова из нулей. На этом описание субблока завершено. Эти восемь байт нулей являются последними в субблоке последнего блока. Следовательно, они же будут последними во всём файле ses.

В процессе обдумывания проекта мне пришла ещё одна идея: добавить в мультисессию маркеры (точки кью), расставив их через каждый час и подписав к ним соответствующие метки. Если сравнивать эту мысль с предыдущей статьёй, то это полная аналогия вертикальных линий на диаграмме, расчерченных через каждый час. Для того чтобы в мультисессии присутствовали точки кью, необходимо учесть шестой блок под названием cues. Я не стал разбираться в байтах данного блока. По аналогии с блоком stat, в созданной мультисессии на 24 часа я расставил 23 точки кью вручную через каждый час и дал им соответствующие имена. Затем я сохранил мультисессию в отдельный ses файл, вырезал содержимое блока cues и сохранил его в файл cues_24h.BLK. При разработке программы этот файл будет учтён. Байты этого файла показаны на рисунке 16. Не знаю почему, но сохранил я именно содержимое, без заголовка и поля размера содержимого (в отличие от stat_31_full.BLK). Эти два слова допишутся в коде программы. А размер содержимого составляет 556 байт. Из них 4 байта занимает подзаголовок (количество точек кью) и 23 субблока по 24 байта каждый. На рисунке 16 заливкой показаны байты содержимого первого субблока. Имена точек кью (метки) я решил сделать такие: 01h, 02h,, 23h.


Рис. 16. Байты содержимого блока точек кью cues для моей мультисессии.

На этом можно завершить описание формата мультисессии. Теперь имеется необходимый багаж знаний, чтобы начать писать программу формирования мультисессии. Написание программы более лёгкая задача, по сравнению с изучением и расшифровкой формата ses. С программой я справился за два вечера, а на изучение формата я потратил не меньше одной недели. Тем более программу я писал, прибегая к ранее используемым функциям, в частности, работы с файлами и каталогами. Поэтому основной опорой для написания программы служили не справочники или Интернет, а прошлые мои проекты, о которых я также писал на хабре. Из Интернета я взял только одну функцию, возвращающую день недели по дате. Но прежде чем привести текст программы, я решил поделиться ещё кое-какой информацией, о чём я изначально не хотел писать в этой статье.

Идея сформировать мультисессию из записей телефонных разговоров мне пришла, когда я работал в более свежей версии программы Adobe Audition 3.0, поддерживающий ввод/вывод звука через ASIO. При сохранении мультисессии я обнаружил, что её можно сохранить на выбор в двух форматах: обычный классический SES и новый формат XML, чего не было в прошлых версиях программы. Сохранив сессию в XML формате, я сразу же открыл этот файл в блокноте, где обнаружил описание кучи параметров, связанных между собой в сложную иерархическую структуру. Для удобства просмотра данной иерархии я воспользовался программой WMHelp XmlPad. На рисунке 17 представлен скриншот данной программы с открытым в нём файлом пробной простой мультисессии. Слева представлена иерархия документа. Активным (выбранным) элементом иерархии является параметр длины первого аудиофайла, стоящий в первом субблоке блока описания аудиофайлов.


Рис. 17. Вид фрагмента XML мультисессии Adobe Audition 3.0.

Я решил изучить именно этот формат, и в дальнейшем программно генерировать нужный XML текст, получая на выходе нужную мне мультисессию. Была даже идея воспользоваться для этих целей программой Excel. Сложность была в том, что около 95% всего XML файла занимает блок с описанием треков. Там колоссальное число параметров, исключить которые без нанесения вреда мультисессии мне не получилось. Дело в том, что в данной версии Adobe Audition гораздо больше функций, относящихся к трекам. По логике вещей для моей простой мультисессии в этих функциях нет никакой нужды. Однако, исключая соответствующие поля из XML документа, сессия перестаёт жить. И мне пришлось бы тянуть этот огромный кусок текста в описании каждого трека для простейшей сессии. Это единственное неудобство при формировании XML файла мультисессии. Знания, полученные при изучении текстового XML варианта мультисессии, безусловно, пригодились во время изучения бинарного ses. И даже в XML некоторые параметры я не смог расшифровать. Поля каждого параметра имеют сокращённое название на английском языке, но даже при этом я не всегда понимал, что это за параметр. Главное мне удалось изучить и расшифровать основные необходимые параметры, их иерархические блоки и поля. Потом меня долго мучил вопрос: как такую сессию открыть в более старой версии программы Adobe Audition? Новые версии программ имеют слишком навороченный интерфейс (чуть ли не 3D), что весьма неудобно для визуализации мультисессии, как диаграммы. Да и из-за этого три-дэ в Adobe Audition 3.0 при полностью развёрнутом окне на FullHD экране помещается максимум (при минимальном масштабе) 28 треков. А в Adobe Audition 1.5 помещалось бы 37 (рис. 18, масштаб 1:2). Всего же нужно показать на экране 31 трек.


Рис. 18. Сравнение фрагментов окон Adobe Audition двух разных версий.

Но больше всего меня добило качество звучания при воспроизведении мультисессии с частотой 8000 Гц в новой версии программы. Звучание не очень хорошее, присутствуют гармонические искажения. Это связано с тем, что вывод звука производится на другой частоте семплов (48 кГц), а ASIO по-другому не может. При выборе в настройках другого устройства вывода Audition 3.0 Windows Sound ситуация не изменяется. Классические DirectSound устройства вывода новая версия программы не поддерживает (версию 3.0 я называю новой). На рисунке 19 показан спектр звучания при воспроизведении в Adobe Audition 3.0 аудио 8 кГц (или сессии) с присутствующими гармоническими искажениями в виде перевёрнутого спектра. Зелёным цветом обведены те частоты, которые должны звучать в идеале (и ничего, кроме них). А красным цветом обведены частоты, являющиеся дополнительным искажением. Скорее всего этот эффект проявляется из-за отсутствия фильтрации после процедуры апсемплинга. Именно после этого я решил взяться за изучение бинарного формата SES более простой и приятной программы Adobe Audition 1.5. Надеялся, что после изучения человеческого XML формата от программы более новой версии мне не составит особого труда в этом разобраться, учитывая опыт работы с бинарными файлами. Так оно и вышло: я довольно быстро раскрутил SES формат. И главное, что обратная совместимость, забегая вперёд, вполне работает: сессия, сформированная для версии 1.5, успешно открывается в версии 3.0. Выше я указал недостатки Adobe Audition 3.0, связанные с качеством звучания и графическим интерфейсом. Но у этой версии программы есть преимущества в навигации по мультисессии. Например, есть возможность оперативного прослушивания одного аудиоклипа в мультисессии при клике по нему мышкой с последующим сдвигом вправо.


Рис. 19. Гармонические искажения при воспроизведении.

Теперь приведу текст программы под спойлером. Программа, разумеется, не имеет графического интерфейса, так как для данной задачи он и не требуется. Текст программы снабжён подробными комментариями, поэтому в дополнительном пояснении не нуждается. Программа запускается в командной строке и в течение секунды обрабатывает список из четырёх сотен файлов, формируя файл мультисесии. Внутри программы имеются четыре параметрические переменные, которые при желании позволяют не формировать маркеры кью, не ставить R на треки выходных дней, не ставить свойство Фиксировать во времени на клипы и выбрать критерий раскраски клипов (по типу вызова или по телефонным номерам). Данные три переменные нужно было бы исключить из текста программы и вывести наружу, то есть в отдельный файл с параметрами программы.

Исходный код программы на C
/********************************************************************В папке "RMC" на диске имеется множество папок, в которыхсодержатся файлы wav с записями телефонных звонков. Файлы имеют имяопределённого формата, который задаётся соответствующим приложением.Для удобства папки имеют имена в формате yyyy-mn, соответствующиегоду и месяцу. Внутри находятся записи за соответствующий срок.Программа при запуске запрашивает имя папки (т.е. год-месяц), из записейкоторой необходимо сформировать мультисессию. Результирующий файлсохраняется в том же каталоге, где расположена обрабатываемая папка,то есть в папке "RMC" на диске "I:".*********************************************************************/#include <windows.h>#include <stdio.h>#include <string.h>DWORD wr; //Сюда пишется, сколько байт прочитано;DWORD ww; //Сюда пишется, сколько байт записано;DWORD wi; //Сюда пишется, сколько байт записано;//День недели по дате (эту функцию я нашёл в интернете);int Date( int D, int M, int Y ){    int a, y, m, R;    a = ( 14 - M ) / 12;    y = Y - a;    m = M + 12 * a - 2;    R = 6999 + ( D + y + y / 4 - y / 100 + y / 400 + (31 * m) / 12 );    return R % 7;}//Открыть файл для чтения;HANDLE openInputFile(const char * filename) {       return CreateFile ( filename,      // Open Two.txt.            GENERIC_READ,          // Open for writing            0,                      // Do not share            NULL,                   // No security            OPEN_ALWAYS,            // Open or create            FILE_ATTRIBUTE_NORMAL,  // Normal file            NULL);                  // No template file       }//Открыть файл для записи;HANDLE openOutputFile(const char * filename) {       return CreateFile ( filename,      // Open Two.txt.            GENERIC_WRITE,          // Open for writing            0,                      // Do not share            NULL,                   // No security            OPEN_ALWAYS,            // Open or create            FILE_ATTRIBUTE_NORMAL,  // Normal file            NULL);                  // No template file       }//Перейти на позицию в файле;void filepos(HANDLE f, __int64 p){  LONG HPos;  LONG LPos;  HPos = p>>32;  LPos = p;  SetFilePointer (f, LPos, &HPos, FILE_BEGIN);}//Запись 32-битного целого числа;void write32(HANDLE f, signed long int a){  WriteFile(f, &a, 4, &ww, NULL);  }//Заполнить одинаковыми байтами;void fill(HANDLE f, signed long int a, unsigned char c){  unsigned char i;  for(i=0;i<c;i++){    write32(f,a);  }}int main(){  HANDLE out; //Выходной файл мультисессии Adobe Audition;  HANDLE stat; //Файл с готовым содержимым блока "stat" (+ заголовки);  HANDLE cues; //Файл с готовым содержимым блока "cues";  HANDLE lf; //Файл для записи формируемого блока "LISTFILE";  HANDLE blk; //Файл для записи формируемого блока "bk20";  char* week[7]={"ПН", "ВТ", "СР", "ЧТ", "ПТ", "СБ", "ВС"}; //Дни недели по-русски;  unsigned char dm[]={31,29,31,30,31,30,31,31,30,31,30,31}; //Число дней в месяцах;  unsigned char p_cues=1; //Параметр: наличие ежечасных маркеров (cues);  unsigned char p_R=1; //Параметр: визуальный флаг "R" (трек на запись) на трек выходного дня;  unsigned char p_lock=1; //Параметр: фиксировать аудиоклипы во времени;  unsigned char p_color=2; //Критерий цветовой раскраски аудиоклипов;  unsigned char flg; //Вспомогательный флаг, нужен при сопоставлении тел. номеров с цветами;  unsigned long int lfsize=0; //Размер блока "LISTFILE";  unsigned long int blksize=0; //Размер блока "bk20";  unsigned long int smp; //Число семплов ф аудиофайле;  unsigned long int offset; //Смещение аудиоклипа от начала мультисессии;  unsigned int cfile=0; //Число обработанных файлов;  unsigned int cblk=0; //Число обработанных аудиоклипов;  char name[100]; //Имя входного файла (и не только...);  char fullname[100]; //Полное имя входного файла вместе с путём;  char infld[8]; //Имя обрабатываемой папки;  char number[11]; //Часть имени файла с тел. номером;  unsigned char len; //Число символов в имени файла;  printf("Input yyyy-dd name of folder:\n"); //Введите год и месяц;  scanf("%s",infld); //Защита от некорректного ввода пока что отсутствует;  WIN32_FIND_DATA fld; //Создаём структуру для доступа к атрибутам входных файлов;  HANDLE hf; //Входной файл (в обработке не используется, так как нужны только атрибуты);  char buf1[48],buf2[556]; //Вспомогательные буферы для копирования блоков "stat" и "cues";  char str[16]; //Буфер для имени трека;  unsigned long int outpos=0; //Файловый курсор выходного файла;  unsigned char byte; //Вспомогательная переменная для побайтного копирования блоков "LISTFILE" и "bk20";  unsigned char i; //Переменная для цикла;  unsigned char mn,d,dw,h,m,s; //Переменные даты-времени;  unsigned char cdm; //Число дней в выбранном месяце;  int yy; //И отдельно год;  yy=2000+(infld[2]-48)*10+(infld[3]-48); //Получаем год из входной строки;  mn=(infld[5]-48)*10+(infld[6]-48); //Получаем месяц из входной строки;  sprintf(name,"I:\\RMC\\%s.ses",infld); //Формируем полное имя выходного файла (с путём);  out=openOutputFile(name); //Открываем выходной файл для записи;  WriteFile(out, "COOLNESS", 8, &wi, NULL); //Начинаем формировать: сначала запишем главный заголовок;  write32(out,0); //Пока пишем ноль (ибо не знаем, сколько будет весить весь файл);  WriteFile(out, "hdr ", 4, &wi, NULL); //Далее, как по моей спецификации: блок заголовка;  write32(out,936); //Размер блока заголовка статический, равен 936;  write32(out,8000); //Частота семплов в мультисессии;  write32(out,24*3600*8000); //Длинна мультисессии в семплах (соотв. 24 часам);  write32(out,0); //Число аудиоблоков в сессии (пока неизвестно);  write32(out,0x00010020);  write32(out,0);  write32(out,0x3ff00000);  write32(out,0);  write32(out,0x3ff00000);  filepos(out,328); //Оставляем позади кучу нулей;  write32(out,0x20);  WriteFile(out, "Мастер", 6, &wi, NULL); //Так надо типа;  filepos(out,376); //Оставляем позади кучу нулей;  write32(out,0x3ff00000);  filepos(out,892); //Оставляем позади кучу нулей;  write32(out,0x0430041c);  write32(out,0x04420441);  write32(out,0x04400435);  filepos(out,956); //Оставляем позади кучу нулей;  stat=openInputFile("stat_31_full.BLK"); //Переписываем блок состояния сессии из заготовки,  ReadFile(stat, &buf1, 48, &wr, NULL); //ибо я не заморачивался с его побайтным разбором;  WriteFile(out, buf1, 48, &wi, NULL);  CloseHandle(stat);  if(mn==2){ //Если февраль,    if(!(yy%4)){ //и если високосный год,      cdm=29; //то 29 дней,    }else{      cdm=28; //иначе - 28;    }  }else{ //Если не февраль,    cdm=dm[mn-1]; //то число дней берём из заранее подготовленного массива;  }  WriteFile(out, "trks", 4, &wi, NULL); //Готовимся формировать блок с треками;  write32(out,4+cdm*152); //Размер блока с треками можно расчитать так;  write32(out,cdm); //Число треков соответствует числу дней в выбранном месяце;  outpos=1016; //Не забываем обновлять переменную файлового курсора;  for(i=0;i<cdm;i++){ //Цикл на число дней в выбранном месяце    dw=Date(i+1,mn,yy); //Получам номер дня недели по дате;    write32(out,0); //Такие константы часто втречаются в файле ses, но я не знаю что это такое;    write32(out,0x3ff00000);     write32(out,0); //Скорее всего это 8-байтовый тип double;    write32(out,0x3ff00000);    if((dw%7==5||dw%7==6)&&p_R){ //Если текущий трек - выходной день, и если разрешено ставить маркер "R",      write32(out,4); //тогда тавим флаг для маркера "R",    }else{      write32(out,0); //иначе - не ставим ничего;    }    sprintf(str,"%02d.%02d.%i %s",i+1,mn,yy,week[dw]); //Формируем имя трека, как моей душе угодно;    WriteFile(out, str, strlen(str), &wi, NULL);    filepos(out,1072+152*i); //Именно в этой позиции заканчивается имя (i+1)-го трека;    write32(out,1); //Далее идут константы, в которых я не разбирался;    write32(out,1);    write32(out,4);    write32(out,0);    write32(out,0);    write32(out,0x40590000);    write32(out,0);    write32(out,0);    write32(out,0xffffff9d);    write32(out,0xffffff9d);    write32(out,i+1); //Приписываем идентификатор трека, как его порядковый номер;    fill(out,0,11);    write32(out,4);    write32(out,0);    outpos+=152; //Обновляем файловый курсор;  }  if(p_cues){ //Если задано в параметре расставить маркеры через каждый час, то формируем блок "cues";    WriteFile(out, "cues", 4, &wi, NULL); //Предварительно формируем заголовок,    write32(out,556); //а также - размер содержимого;    cues=openInputFile("cues_24h.BLK"); //Данный блок уже готовый, но без заголовка;    ReadFile(cues, &buf2, 556, &wr, NULL); //(хотя можно было сделать полностью, как в "stat");    WriteFile(out, buf2, 556, &wi, NULL);    CloseHandle(cues);    outpos+=564;  }  DeleteFile("LISTFILE"); //Предварительно удалив (если они существуют от предыдущей работы программы)  DeleteFile("bk20"); //временные файлы "LISTFILE" и "bk20",  lf=openOutputFile("LISTFILE"); //открываем (создаём) их для накопления содержимым  blk=openOutputFile("bk20"); //в результате сканирования папки с входными файлами;  WriteFile(lf, "LISTFILE", 8, &wi, NULL); //Перед сканированием папки записывам заголовки блоков;  WriteFile(blk, "bk20", 4, &wi, NULL);  write32(lf,0);  write32(blk,0);  write32(blk,0);  write32(blk,0x48); //Как я выяснил, это длина подблока для одного аудиоклипа;  sprintf(name,"I:\\RMC\\%s\\*.wav",infld); //Шаблон поиска всех wav файлов в запрашиваемой папке;  hf=FindFirstFile(name,&fld); //Ищем первый файл;  do{ //Затем следующие файлы;    len=strlen(fld.cFileName); //Число символов в имени файла;    for(i=10;i>=1;i--){ //Переписываем последние 10 символов имени файла в буфер номера;      number[10-i]=fld.cFileName[len-i-4]; //Без расширения файла;    }    number[10]=0; //Выставляем ноль в конце, как признак конца строки;    cfile+=1; //Увеличиваем счётчик количества файлов;    sprintf(fullname,"I:\\RMC\\%s\\%s",infld,fld.cFileName); //Формируем полное имя файла с путём;    d=(fld.cFileName[22]-48)*10+(fld.cFileName[23]-48); //Вычисляем дату (день) из имени файла;    h=(fld.cFileName[25]-48)*10+(fld.cFileName[26]-48); //Вычисляем час из имени файла;    m=(fld.cFileName[27]-48)*10+(fld.cFileName[28]-48); //Вычисляем минуту из имени файла;    s=(fld.cFileName[29]-48)*10+(fld.cFileName[30]-48); //Вычисляем секунду из имени файла;    offset=(h*3600+m*60+s)*8000; //Вычисляем смещение аудиоклипа в сессии;    smp=(fld.nFileSizeLow-44)/4; //Вычисляем длительность аудио в семплах (псевдовычисление через размер файла);    WriteFile(lf, "wav ", 4, &wi, NULL); //Начинаем формировать запись подблока списка файлов;    write32(lf,17+strlen(fullname)); //Запись размера подблока (его можно вычислить именно так);    write32(lf,1000+cfile); //Идентификатор файла (можно рандомно, но я решил начать с 1000 и по порядку);    write32(lf,0x14); //Тип файла (формат аудио);    WriteFile(lf, fullname, strlen(fullname), &wi, NULL); //Путь к файлу (полное имя);    WriteFile(lf, "\0", 1, &wi, NULL); //Конец строки полного имени;    write32(lf,0xffffffff); //Отступ;    write32(lf,smp); //Длительность аудио в семплах;    lfsize+=(25+strlen(fullname)); //Обновляем размер блока "LISTFILE";    cblk+=1; //Формируем блок аудиоклипа на текущий аудиофайл;    write32(blk,0); //Здесь должна быть ссылка на огибающую, но они в нашей задаче не востребованы;    write32(blk,1000+cfile); //Ссылка на аудиофайл (соответствие);    write32(blk,0); //Опять те самые константы;    write32(blk,0x3ff00000);    write32(blk,0);    write32(blk,0x3ff00000);    write32(blk,offset); //Записываем смещение аудиоклипа в мультисессии;    if(((24*3600*8000)-offset)>smp){ //Если аудиофайл (по длительности) не выходит на следующие сутки,      write32(blk,smp); //оставляем длительность аудиоклипа в мультисессии полной,    }else{      write32(blk,(24*3600*8000)-offset); //иначе обрезаем длительность аудиоклипа на конце текущих суток;    }    write32(blk,0); //Начало аудиоклипа совпадает с началом аудиофайла;    if(p_lock){ //Если в параметре задана фиксация аудиоклипов во времени,      write32(blk,0x0008000a); //дополняем флаговый блок соответствующим битом (3 бита из 32 установлены),    }else{      write32(blk,0x00080008); //иначе оставляем без этого бита(2 бита из 32 установлены);    } //Один из двух битов выше - флаг свойства "клип только для воспроизведения";    write32(blk,d); //Ссылка на трек (соответствует дате);    fill(blk,0,4); //Куча нулей;    switch(p_color){ //Признак цветовой раскраски аудиоклипов;      case 1: //Входящий или исходящий вызовы;        switch(fld.cFileName[0]){ //Анализируем первый символ в имени файла;          case 'I': //Если "I" (псевдо признак входящего вызова),            write32(blk,0); //записываем красный цвет;          break;          case 'O': //Если "O" (псевдо признак исходящего вызова),            write32(blk,102); //записываем зелёный цвет (значение по умолчанию);          break;          default: //Если вдруг что-то другое,            write32(blk,102); //оставляем значение по умолчанию;          break;        }      break;      case 2: //Раскраска по номерам;        flg=0; //Сбрасываем флаг;        if(!strcmp("9530000000",number)){ //Если такой-то такой-то номер,          write32(blk,05); //то цвет такой-то такой-то,          flg=1; //(номер найден);        }        #include "numbers_and_colors.cpp" //Код со списком номеров и цветов - в отдельном файле (продолжение);        if(!flg){ //Если флаг не поменял значение (номер не был найден в списке),          write32(blk,102); //оставляем цвет клипа по умолчанию;        }      break;    }    write32(blk,0);    write32(blk,0);    if(((24*3600*8000)-offset)<=smp){ //Если аудиофайл (по длительности) выходит на следующие сутки (редкий случай),      cblk+=1; //формируем ещё один аудиоклип на текущий файл;      write32(blk,0); //Далее всё по аналогии, как выше;      write32(blk,1000+cfile);      write32(blk,0);      write32(blk,0x3ff00000);      write32(blk,0);      write32(blk,0x3ff00000);      write32(blk,0); //Но теперь данный аудиоклип ставится в самое начало мультисесисии,      write32(blk,smp-((24*3600*8000)-offset)); //по длине на оставшееся время,      write32(blk,(24*3600*8000)-offset); //и звучит не сначала аудиофайла, а как продолжение предыдущего аудиоклипа;      if(p_lock){        write32(blk,0x0008000a);      }else{        write32(blk,0x00080008);      }      write32(blk,d+1); //Ставим второй (дополнительный) аудиоклип на следующий трек (день);      fill(blk,0,4);      switch(p_color){ //В зависимости от параметра критерия раскраски;        case 1: //Раскраска по типу вызова;          switch(fld.cFileName[0]){ //Распознаём по первому симполу в имени файла (псевдо признак);            case 'I': //Если входящий,              write32(blk,0); //то цвет красный;            break;            case 'O': //Если исходящий,              write32(blk,102); //то цвет зелёный, как по умолчанию;            break;            default: //Если вдруг что-то ещё (не дай бог),              write32(blk,102); //то цвет по умолчанию;            break;          }        break;        case 2: //Раскраска по номерам;          flg=0;          if(!strcmp("9530000000",number)){ //Если такой-то такой-то номер,            write32(blk,05); //то цвет такой-то такой-то,            flg=1; //(номер найден);          }          #include "numbers_and_colors.cpp" //и так для всех раскрашиваемых номеров (во вложении);          if(!flg){ //Если номер не найден,            write32(blk,102); //то цвет по умолчанию;          }        break;      }      write32(blk,0);      write32(blk,0);    }    }while(FindNextFile(hf,&fld)); //Пока не кончатся все wav файлы;  filepos(lf,8);  write32(lf,lfsize); //Записываем размер блока "LISTFILE", который накапливали в переменную;  filepos(blk,4);  blksize=8+72*cblk; //Расчитываем размер блока "bk20", зная количество аудиоклипов;  write32(blk,blksize); //Записываем размер блока "bk20";  write32(blk,cblk); //Записываем количество аудиоклипов;  blksize+=8; //Корректируем размер блока "bk20", чтобы приравняться к размеру соотв. временного файла;  lfsize+=12; //Корректируем размер блока "LISTFILE", чтобы приравняться к размеру соотв. временного файла;  CloseHandle(lf); //Закрываем врем. файл;  CloseHandle(blk); //Закрываем врем. файл;  lf=openInputFile("LISTFILE"); //Открываем врем. файл на чтение для перезаписи в основной;  do{ //Перезапись происходит побайтно, пока не конец файла (есть байты на чтение);    ReadFile(lf, &byte, 1, &wr, NULL);    if(wr){      WriteFile(out, &byte, 1, &wi, NULL);    }  }while(wr);  CloseHandle(lf); //Закрываем врем. файл;  blk=openInputFile("bk20"); //Открываем врем. файл на чтение для перезаписи в основной;  do{ //Перезапись происходит побайтно, пока не конец файла (есть байты на чтение);    ReadFile(blk, &byte, 1, &wr, NULL);    if(wr){      WriteFile(out, &byte, 1, &wi, NULL);    }  }while(wr);  CloseHandle(blk); //Закрываем врем. файл;  outpos=outpos+blksize+lfsize; //Обновляем файловый курсор выходного файла;  filepos(out,8);  write32(out,outpos-12); //Записываем в начале выходного файла размер содержимого;  filepos(out,28);  write32(out,cblk); //Записываем в блок главного заголовка число аудиоклипов;  CloseHandle(out); //Выходной файл мультисессии готов! Закрываем его;  printf("c_files: %i\nc_block: %i\n",cfile,cblk); //Выводим информацию на экран (число файлов и клипов);  system("PAUSE");  return 0;}


Теперь можно привести скриншоты с результатами. Их будет несколько: в разных масштабах просмотра, в разных версиях программы и с разными критериями раскраски. Обрабатывался каталог 2020-05, то есть, записи за май текущего года. Всего обработано 446 записей. Количество блоков такое же, так как записи с переходом на новые сутки отсутствуют.


Рис. 20. Вид мультисессии в полном масштабе с раскраской по тел. номерам.


Рис. 21. Вид мультисессии в полном масштабе с раскраской по типу вызова.


Рис. 22. Вид мультисессии в среднем масштабе.


Рис. 23. Вид мультисессии в крупном масштабе.


Рис. 24. Вид той же мультисессии в Adobe Audition 3.0.

Подробнее..

Моя музыка 2020 года в картинках и графиках

26.12.2020 16:10:02 | Автор: admin

Иногда я пишу научные статьи. Но перед Новым годом хочется немного отвлечься от звериной серьёзности науки. Значит, можно написать несерьёзную и не совсем научную! Но основанную на данных и их статистическом анализе, с графиками и воспроизводимыми результатами.

Введение

В конце года Яндекс-музыка подводит итоги: самые популярные песни, альбомы и исполнители. Я открыл итоги за 2020-й и понял, что у меня специфические вкусы: на 100 треков одно совпадение. Впрочем, чему я удивляюсь? И так понятно, что мой любимый жанр A, мои любимые группы B и C, а вот эти все D, E, F, G, H я как-то не очень принимаю. Но хорошо ли я разбираюсь в своих музыкальных вкусах? Не помню даже, что я делал в начале года, а уж какая музыка мне тогда нравилась и подавно К счастью, есть количественные методы, которые помогут пролить свет на загадки моих предпочтений в музыке.

Яндекс-музыка сделала не только общие, но и личные итоги. У меня появился плейлист Мой 2020. В нём 50 треков. Можно проанализировать его статистически и посмотреть, каких исполнителей и жанров там больше всего, когда вышли песни, на каком языке написаны тексты и какие слова в них наиболее часто встречаются.

Данные и методы

Сначала нужно собрать данные. Я перенёс в таблицу порядковые номера в плейлисте, названия треков и исполнителей, потом зашёл на страницу каждого трека и выписал жанр. С годом выхода пришлось повозиться: некоторые старые песни идут в переизданиях, поэтому уточнял по Википедии. С языком, наоборот, всё сразу понятно. Ещё я сделал колонку с текстом: его тоже можно проанализировать. Для трёх песен на финском текста не нашёл оставил поля пустыми. Если бы песен было не 50, а 500, то сбор данных пришлось бы автоматизировать, а так справился вручную. Таблица в итоге выглядит примерно так.

Первые три строки таблицы с даннымиПервые три строки таблицы с данными

Теперь берём эту таблицу и анализируем. Вот только как лучше всего это сделать?

Самый простой вариант посчитать как есть. Надо сказать, такой способ тоже даёт некоторые результаты. Например, в плейлисте 27 исполнителей в среднем получается 1,9 треков на каждого. Что ж, относительное разнообразие. При этом на исполнителя приходится либо одна песня (таких 15), либо три (таких 11), и только у одной группы в плейлисте две песни. Кроме того, можно сделать вывод, что больше всего песен на английском 32. На немецком 8, на русском 7, и ещё есть 3 песни на финском.

Но есть тонкость. Мы считаем песни так, как будто они равнозначны. А на самом деле у нас плейлист, в котором песни идут в определённом порядке. Я не знаю, почему они расположены именно так. Легче всего предположить, будто это топ-50 самых прослушиваемых треков за год. Но вряд ли: в плейлисте есть песни, которые я включал раз-другой, но нет тех, которые играли каждый день в течение месяца. Похоже, что Яндекс собирал плейлист по хитрому алгоритму, где порядковый номер песни зависит не только от количества прослушиваний. А может быть, количество прослушиваний вовсе не имеет значения. Но так или иначе, я полагаю, что песни в плейлисте идут от самых важных к менее важным, пусть даже эта важность определяется непонятно как. Следовательно, песни не равнозначны, и неравнозначность нужно учитывать.

Как сделать поправку на то, что одни песни важнее других? Добавить веса. Проще говоря, написать рядом с каждой песней число, которое характеризует её важность. Например, если есть две песни с весами 2 и 3 и одна песня с весом 7, то одна песня перевесит две остальные, потому что её вес (7) больше, чем суммарный вес двух других (5).

Подобрать веса можно по-разному. Я перепробовал кучу вариантов.

В итоге остановился на таком.

Это логистическая функция. По-моему, такой график лучше всего характеризует субъективную важность песен: в начале у всех примерно одинаковый и большой вес, потом в какой-то момент важность начинает резко уменьшаться, а в конце плейлиста вес снова примерно одинаковый, но уже небольшой. Вес первой песни почти единица, последней почти ноль, средней ровно 0,5.

Теперь, когда мы расставили веса, переходим к нормальному анализу.

Результаты

Начнём с исполнителей. Если помните, у первых трёх песен в таблице с данными исполнители шли в таком порядке: Lindemann, Lordi, Imagine Dragons. Как думаете, кто три первые исполнителя по суммарному весу песен?

Правильный ответ: Lindemann, Lordi и Imagine Dragons. Ещё Rammstein очень близко, но всё же на четвёртом месте. Sampsa Astala, который на пятом месте, выглядит как мой личный прорыв года, потому что у него всего-то 16 песен вообще, и первую из них я послушал полтора месяца назад а он за эти полтора месяца забрался аж на пятое место.

Переходим к жанрам. Тут Industrial & Rock Hallelujah, а возможно, и Hard Rock Hallelujah.

Я понимаю, что с жанрами, наверное, не всё идеально. Иностранной рок и поп меня смущают не слишком ли общие названия? Но сам я плохо разбираюсь в жанрах, поэтому оставил так, как на Яндекс-музыке.

О языках я уже говорил, но любопытно посмотреть, влияют ли веса. И они влияют!

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

Наконец, нарисуем график с годами выхода песен.

Я нарисовал две линии: тонкую без сглаживания, жирную со сглаживанием. Без сглаживания слишком много острых пиков со сглаживанием хронологию видно лучше. Мне немного напомнило схему волны цунами: в океане она невысокая, потом к берегу растёт.

Схема волны цунамиСхема волны цунами

Интересно тогда, где там в прошлом лежит эпицентр землетрясения, которое породило эту волну? В 60-х? В джазе? (Я догадываюсь, какой должен быть ответ, но не скажу.)

На первый взгляд, это все результаты, которые можно было выжать из моего небольшого набора данных. Хотя нет, есть ещё тексты. С текстами можно сделать как минимум одну забавную штуку: посмотреть, какие слова встречаются чаще всего.

Я не анализировал тексты на русском и немецком, потому что их мало. Ну ладно, если совсем честно, то я их проанализировал и понял, что результат искажённый. По-русски самое частое слово внутри, потому что Distemper поёт: Ты настоящий лишь внутри, внутри, внутри. В немецких текстах на первом месте Moskau благодаря Чингисхану, а на втором allesfresser из одноимённой песни Lindemann. Песен на английском 32, поэтому результаты должны меньше зависеть от слов, которые повторяются в отдельных песнях.

Отмечу две технические подробности анализа. Во-первых, слова приводятся к начальной форме. Это нужно, чтобы посчитать listen, listens, listened и listening как одно слово listen. Во-вторых, из текстов удаляются стоп-слова те, которые встречаются чаще всего и не несут большого смысла, например: I, he, is, a, the.

Я считал по-разному: сначала просто количество слов, потом tf-idf. Tf-idf значит term frequency / inversed document frequency. Это тоже способ расставить веса, только не песням, а словам. Некоторые слова часто встречаются не только в тексте данной песни они вообще часто используются. А некоторые слова встречаются редко, но и сами по себе редко используются. Tf-idf позволяет придать больший вес тем словам, которые редко используются, но важны для конкретного текста. Ещё, пожалуй, можно было бы использовать веса песен: у слова из песни, которая на втором месте, вес больше, чем у слова из пятнадцатой песни. Однако, по-моему, так слишком легко запутаться. И вообще не факт, что важность слова зависит от важности песни: некоторые ценные фразы есть в песнях из последней десятки.

Словом, в итоге я просто нашёл самые частые слова в текстах песен и нарисовал их в виде облака слов.

Результат анализа текстов оказался несколько неожиданным для меня. Ладно Lindemann, индастриал и английский язык, но я ни за что бы не подумал, что слова heart, take и feel будут самыми частыми. Может, надо было всё-таки с tf-idf считать? Там head и heart окажутся в начале. А потом языковая экзотика в виде слова countdown из The Final Countdown, а ещё zombie из одноимённой песни The Cranberries В общем, лучше без tf-idf.

Выводы

  1. Мои представления о собственных музыкальных вкусах несколько отличаются от моих музыкальных вкусов на самом деле. Ну, или как минимум от того, что я слушал в течение 2020 года.

  2. Группа года Lindemann, жанр года индастриал, песня года Allesfresser.

  3. Чаще всего я слушаю песни на английском, хотя и песнями на других языках не брезгую.

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

Вообще же нужно учитывать подводные камни. Об одном я уже говорил: непонятно, как Яндекс-музыка делала мой плейлист 2020. Может быть, там всё намешано непонятно как, потому что составляла Могучая нейросеть по критериям, которые неизвестны даже разработчикам Яндекса. Второй нюанс: нужно смотреть статистику не только по Яндексу, но ещё и по ВКонтакте и чуть-чуть по Ютуб-музыке.

Цифр по ВКонтакте у меня нет, но навскидку там должно быть много Lordi и Sampsa Astala, а Lindemann, наоборот, меньше. Разрыв между Lindemann и Lordi небольшой, и к тому же Lindemann это в некотором смысле продолжение Rammstein, а их я начал слушать в 2019, а Lordi находка исключительно 2020-го, потому что до середины 2020-го я был уверен, что кого-кого, а этих не буду слушать никогда. На второе место Lordi вышли всего-то за полгода, а если экстраполировать на год Словом, выводы нужно скорректировать: группой 2020 года у меня становятся вот эти натуральные чудовища.

Группа Lordi в текущем составеГруппа Lordi в текущем составе

Ну ладно не такие уж и чудовища на самом деле.

Если что, это старый состав группы. Сампса Астала (Кита), Нико Хурме (Калма) и Леэна Пейса (Ава) уже не в группе, поэтому им можно показывать лица, а самому Mr. Lordi нельзяЕсли что, это старый состав группы. Сампса Астала (Кита), Нико Хурме (Калма) и Леэна Пейса (Ава) уже не в группе, поэтому им можно показывать лица, а самому Mr. Lordi нельзя

Будет интересно сравнить, когда Яндекс-музыка пришлёт письмо с итогами 2020 года: они там обычно пишут, какая у тебя любимая группа и песня, а ещё сколько ты всего за год музыки слушал.

Направления дальнейших исследований

  1. Использовать больше методов анализа текста. Облако слов неплохо выглядит, но есть куда более продвинутые приёмы: тематическое моделирование и анализ тональности. Первый расскажет, о чём песни, а второй об их настроении. К сожалению, я пока этими методами не владею. А ещё боюсь, что они не справятся с переносным смыслом и отправят Fish On в охоту и рыболовство, а AUSLNDER в туризм и путешествия.

  2. Сравнить себя с друзьями.

  3. Уговорить ВК и Яндекс сделать общедоступный АПИ, чтобы выкачать всю свою статистику и провести исследование на полном наборе данных. Вряд ли получится, к сожалению.

  4. Зарегистрироваться на Last.fm, чтобы не изобретать велосипед.

Напоследок: как и положено количественному воспроизводимому исследованию, все данные и код лежат у меня на Гитхабе. Кроме того, картинка на обложке это тоже график, сделанный с помощью ggplot2.

Подробнее..

Перевод 6 принципов эффективной визуализации данных

03.01.2021 20:22:24 | Автор: admin

Ключевые принципы создания полезных и информативных графиков


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

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

Тем не менее при написании этой статьи я черпал вдохновение в книге Эдварда Тафта Beautiful Evidence, которая содержит шесть принципов, посвящённых тому, как сделать графики данных полезными. Именно эти принципы отделяют полезные графики от бесполезных.

Эта статья также в значительной степени вдохновлена книгой Роджера Д. Пенга Exploratory Data Analysis in R Она доступна бесплатно на Bookdown, и вы можете прочитать её, чтобы узнать больше о EDA.

Давайте ближе познакомимся с этими принципами.


Пример визуализации данных на Our World in Data



1. Покажите сравнение (контрольная и экспериментальная группы)


Демонстрация сравнения основа хорошего научного исследования. Доказательства гипотезы всегда связаны с чем-то другим. Возьмём пример: вы говорите: Тёмный шоколад улучшает концентрацию внимания и способность к обучению. Важный вопрос в этом утверждении по сравнению с чем? Без сравнения (относительная гипотеза) утверждение бесполезно.

Один из способов показать сравнение контрольная и экспериментальная группы. Люди одной группы будут есть шоколад, люди во второй группе не будут. Таким образом, вы сможете сравнить влияние шоколада на концентрацию и способность к обучению на основе результатов теста или путём измерения активности мозга.

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

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

2. Причинно-следственная связь и объяснение


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

Возвращаясь к предыдущему примеру, допустим, что испытуемые из экспериментальной группы получили более высокие баллы по тесту, и это показывает, что тёмный шоколад улучшает концентрацию. Важный вопрос: почему это именно так?

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

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

3. Данные со многими переменными (более двух переменных)


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

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

Возьмем парадокс Симпсона, парадокс в вероятностной статистике, когда при объединении групп исчезает тенденция, возникающая в разных группах данных. Чтобы проиллюстрировать:

  • Две переменные отрицательная связь.
  • Три переменные положительная связь (x, y, z) (есть путающие переменные).

4. Не позволяйте инструментам управлять анализом


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

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

Например, вместо того чтобы создавать отчёты, содержащие только текст, используйте инфографику: изображения, диаграммы, слова, числа и т. д., всё это обогатит информацию. Обладая обилием информации и графиков, читатели могут наблюдать множество различных корреляций доказательства в одном месте. Так что помните, что вы рассказываете историю. Не позволяйте инструментам ограничивать ваше мышление. Пусть анализ управляет инструментами, создаёт сногсшибательные, богатые доказательствами графики.

5. Документируйте свои графики соответствующими метками, шкалами и источниками данных


Когда вы впервые смотрите на график, то сначала видите заголовок, а затем метки контекста графика. Без них график не рассказывает ничего. Хорошие отчёты/графики должным образом документируются, при этом каждому графику присваиваются соответствующие шкалы и метки. Источники данных, используемые для создания графиков, также имеют решающее значение. Таким образом, хорошая практика заключается в сохранении кода, который применялся для генерации данных и графиков: это позволяет воспроизводить данные. Это также добавляет достоверности вашим графикам. Более того, сохраняя код, вы можете редактировать график в случае необходимости.

6. Содержание превыше всего


В конечном счёте, независимо от всех вышеперечисленных принципов, без контента, качественного, актуального и целостного, ваша графика будет бесполезна или она будет вводить в заблуждение. Другими словами, мусор внутри, мусор снаружи. Прежде чем сообщать о каком-либо результате, убедитесь, что результат это нечто интересное и важное. Независимо от того, насколько красива или наглядна ваша графика, бесполезные результаты никому не нужны. Нечто интересное это личный опыт или что-то, навеянное Интернетом. В любом случае всегда задавайте вопросы: так идея становится реальностью.

Заключение


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

  1. Покажите сравнение.
  2. Покажите причины.
  3. Покажите многомерные данные.
  4. Объедините как можно больше доказательств.
  5. Опишите и документируйте график.
  6. Убедись, что ваша история интересна.

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

Я оставляю цитату американского математика Джона Тьюки, который открыл новую эру статистики:

Простой график привнёс больше информации в сознание аналитика данных, чем любое устройство.

Для более глубокого понимания этих принципов я рекомендую обратиться к книге Роджера Д. Пенга Exploratory Data Analysis in R (ссылку на нее я оставлю чуть ниже).

Ресурсы и ссылки


Если вы хотите узнать больше о визуализации данных, посмотрите эти замечательные бесплатные книги:


Платформы, которые демонстрируют красивые визуализации

Руководства по созданию графиков имеются на этих ресурсах

Ссылки для этой статьи


Спасибо, что прочитали!

image



Подробнее..

Развитие BI-систем тренды и движение в сторону ABI. Взгляд со стороны визуализации

04.05.2021 16:09:09 | Автор: admin

Почему привычные нам BI-системы меняются? Куда движется их развитие, какие технологии сейчас внедряются, как можно улучшить аналитику для бизнеса? В этой статье мы коснемся этих вопросов и постараемся ответить, чего следует ожидать в ближайшем будущем от систем бизнес-аналитики.

Заметка от партнера IT-центра МАИ и организатора магистерской программы VR/AR & AI компанииPHYGITALISM.

Кратко о BI-системах и их преимуществах

BI-системы используются в большинстве сфер, поэтому этот термин широко известен в бизнес-сообществе. На пользовательском уровне BI-системы это программное обеспечение, которое помогает работать с данными, анализировать и обрабатывать большие объемы информации. Принцип их работы построен на загрузке всех имеющихся данных в единое хранилище, где информация обрабатывается, а затем появляется в виде готовых интерактивных отчетов и презентаций.

Рис.1. Преобразование данных в аналитику в BI-системахРис.1. Преобразование данных в аналитику в BI-системах

BI-системы собирают всю информацию в одном месте для удобной аналитики и помогают выявлять закономерности и тренды. Загружая в BI-систему данные о рынке мы получаем более полное представление о ситуации, а, значит, и лучшую аналитику.

Рис 2. Для каких задач внедряют BI-системыРис 2. Для каких задач внедряют BI-системы

Внедрение такого ПО, кстати, совсем не требует усилий, так как оно дополняет существующие инструменты. Аналитика становится простой и быстрой, так как для получения анализа BI-система сама собирает все данные о нужных показателях из множества источников и предоставляет информацию для анализа. Сокращение времени и сил за счет одного приложения, которое еще при этом повышает эффективность работы подтверждение актуальности этого инструмента.

Рис 3. Преимущества BI-системРис 3. Преимущества BI-систем

Плюсы BI-систем для бизнеса уже давно известны, все больше компаний внедряют подобные инструменты не только для финансовой аналитики, но и маркетингового и рыночного анализа.

Рис.4. Объем рынка BI-системРис.4. Объем рынка BI-систем

Расширяются границы их применения для стратегического и тактического планирования.

Рис 5. BI-системы как часть бизнесаРис 5. BI-системы как часть бизнеса

Внедрение BI-систем становится все более нужным и прибыльным для компаний.

Рис 6. Эффекты от внедрения BI-систем для компанийРис 6. Эффекты от внедрения BI-систем для компаний

Рынок BI-систем развивается в сторону кроссплатформенности и внедрения новых подходов к аналитике. Именно поэтому важно понимать, какие тренды сейчас есть.

Тренды в развитии BI-систем: эволюция до ABI

Изначально аналитические отчеты разрабатывались сторонними организациями и IT-специалистами. На все интересующие вопросы топ-менеджеров сотрудники отвечали с помощью подготовленных статистических отчетов, подготовка которых занимала много времени и сил. Сам цикл получения аналитики был слишком растянут, что приводило к долгому принятию решений.

Современная бизнес-аналитика устроена по-другому: она интерактивна и доступна. Доступ к данным можно предоставить любому, пользователь может сам найти ответы на вопросы, кликая на интерактивные визуализации: графики, карты, таблицы или диаграммы.

Рис.7. Интерактивность современных BI-системРис.7. Интерактивность современных BI-систем

За все время настолько изменилось представление о BI-системах, что большинство специалистов называют используемые self-service BI-системы (такие как Tableau, Power BI или Qlik Sense) просто BI-системой, хотя различия тут есть в традиционных системах в аналитику были вовлечены IT-специалисты, а в self-service пользователи сами выполняют всю работу, без обращения к IT.

Рис.8. Разница между традиционной и self-service BI-системамиРис.8. Разница между традиционной и self-service BI-системами

Появление ABI-систем

Эволюция BI-систем не стоит на месте, появляются новые подходы к аналитике, а данных становится все больше именно поэтому возникла новая концепция Augmented Business Intelligence, которую выделили Gartner.

Рис.9. Эволюция аналитики в BI-системы и в Augmented Business IntelligenceРис.9. Эволюция аналитики в BI-системы и в Augmented Business Intelligence

Augmented Business Intelligence это модель партнерства людей и искусственного интеллекта, которая ориентирована на совместное взаимодействие машины и человека для улучшения аналитики, принятия решений, подготовки данных и получения инсайтов.

Рис.10. Инновационность ABI-системРис.10. Инновационность ABI-систем

ABI это новая ступень развития BI-платформ, так как в ней есть сразу несколько преимуществ. В ней объединяется не только привычная аналитика и таблицы, но и также новые технологии: от дополненной и виртуальной реальности до решений с компьютерной графикой и 3D.

Рис.11. Отличия BI-системы от ABI-системы и ее преимуществаРис.11. Отличия BI-системы от ABI-системы и ее преимущества

Становится очевидным, что BI-системы эволюционируют, они меняются вместе с обществом, наукой и человеком, и есть ряд трендов, которые свидетельствуют о движении в сторону простой, понятной, удобной и быстрой аналитики.

Рис.12. Тренды в развитии BI-системРис.12. Тренды в развитии BI-систем

Тремя основными тенденциями бизнес-аналитики на 2020 год являются управление качеством данных (MD/DQ), DataViz и внедрение self-service BI-систем, и особое место занимает внедрение data-driven подхода в культуру компаний. Мы стараемся внедрять все эти подходы в наше решение с BI-системой для Ingrad, и хотели бы побольше рассказать о самых интересных, на наш взгляд.

Развитие предиктивной аналитики

Цель любой BI-системы систематизация и агрегация знаний, упрощение аналитического процесса для людей. С развитием технологий искусственного интеллекта аналитические системы смогут не только помочь выявить проблемы, но и дать рекомендации по их решению, а также сделать прогноз развития ситуации в будущем.

В этом контексте также говорят о концепции DIKW: Data-Information-Knowledge-Wisdom.

Рис.13. Концепция DIKWРис.13. Концепция DIKW

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

BI-системы в этом случае выступают инструментом достижения верхушки пирамиды благодаря визуализации мы можем быстро проанализировать любые данные и информацию для получения знаний. Чтобы получить мудрость мы должны видеть всю ситуацию в пространстве, и здесь может помочь визуализация данных (Data Visualization) и 3D-технологии.

Визуализация данных (Data Visualization, DataViz)

Наше потребление информации становится больше визуальным во всем информационном шуме мы неосознанно обращаем больше внимания на изображения и видео, иногда пролистываем большие тексты.

Рис. 14. Визуальное потребление информацииРис. 14. Визуальное потребление информации

Именно поэтому и существует визуализация данных (Data Visualization) ряд инструментов наподобие графиков, таблиц, диаграмм и схем, которые представляют информацию наглядно.

Рис.15. Инструментарий DataVizРис.15. Инструментарий DataViz

Донести информацию с помощью инфографики намного проще и быстрее, чем с помощью текста, но мы хотели бы отметить, что и здесь есть простор для развития, а именно уход в 3D.

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

Рис.16. Преимущества 3D-визуализацииРис.16. Преимущества 3D-визуализации

Мы считаем, что 3D визуализация данных это не просто тренд, а необходимость для некоторых сфер (AEC, например). Для девелопера на рынке российской недвижимости мы разработали BI-систему аналитики с 3D визуализацией данных, которая намного более эффективна благодаря интерактивности и наглядной демонстрации данных на карте.

Рис.17. Пример 3D визуализации данных на карте для визуализации данных в проекте с IngradРис.17. Пример 3D визуализации данных на карте для визуализации данных в проекте с Ingrad

3D в BI-системах может использоваться и для визуализации объектов например, BIM-модели зданий помогают быстро получать нужную аналитику и информацию о строительном объекте.

Рис.18. Пример интерактивных BIM-моделей зданийРис.18. Пример интерактивных BIM-моделей зданий

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

Data Storytelling

Одним из главных трендов, который был выделен исследованием Dresner это data storytelling. Чтобы человек лучше запомнил и воспринял суть информации и сообщения, он должен пережить опыт. Наблюдая за развитием ситуации в реальном времени, мы невольно попадаем в раскрытие какой-либо истории.

Похожая ситуация наблюдается и с данными если мы хотим донести важные сведения, мы должны сконцентрировать все внимание пользователя на них. Именно поэтому в интерактивных презентациях и BI системах мы все чаще встречаемся с визуальными анимированными эффектами, которые фокусируют взгляд на нужной информации.

Рис. 19. Фокусирование внимания пользователя на данных с помощью анимацииРис. 19. Фокусирование внимания пользователя на данных с помощью анимации

С помощью сторителлинга можно подавать большие объемы информации просто и доступно. Если в обычной презентации специалист, взглянув на большой объем данных, не сразу сможет разобраться во показанных вводных, то при использовании сторителлинга мы сразу и наглядно демонстрируем, откуда берутся данные, какие выводы можно сделать из разных массивов.

Рис.20. Феномен data storytellingРис.20. Феномен data storytelling

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

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

Наш BI-инструмент ориентирован на использование руководителем компании для бизнес-аналитики, маркетингового и конкурентного анализа, на презентацию финансовой отчетности топ-менеджменту или совету директоров, и в нем мы объединили тренды и технологии.

Рис.21. Уникальные черты и roadmap разработанной кроссплатформенной BI-системы для IngradРис.21. Уникальные черты и roadmap разработанной кроссплатформенной BI-системы для Ingrad

За какими технологиями нужно следить, чтобы быть в курсе развития BI-систем?

  • Искусственный интеллект и машинное обучение для создания системы предиктивной аналитики, расшифровки данных и выявления тенденций

  • 3D-технологии для внедрения новых инструментов Data Visualization, показа большего числа данных, в том числе с привязкой к географии

  • XR для совместной работы и визуализации аналитики в интерактивном иммерсивном формате.

Заключение

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

Проследив эволюцию BI-систем, тренды и прогнозы развития, которые делают крупные исследовательские компании, выделим целый ряд трендов:

  • MD/MQ Data management

  • Внедрение data-driven культуры в работу

  • Внедрение self-service BI систем

  • Data Visualization

  • Data Storytelling

  • Развитие ABI систем

  • Аналитика в real time

  • Data warehouse modernization

  • Data governance

  • Предиктивная аналитика

  • Внедрение моделей машинного обучения

  • Cloud BI

  • Самостоятельная работа с данными

  • BI-системы для мобильных устройств

  • Добавление и совершенствование уведомлений в BI-системах

Можно сделать вывод, что общая тенденция в развитии BI-систем это уход в сторону упрощения аналитики и предоставления быстрого и полного взгляда на проблему для любого заинтересованного человека (включая тех, кто может не разбираться в аналитике).

Бизнес-аналитика становится проще и доступнее, и развитие технологий только способствует этому.

Источники
Подробнее..

Перевод Как выбрать красивые цвета для вашей инфографики

27.09.2020 22:21:48 | Автор: admin


Очень трудно выбрать хорошие цвета для инфографики. Постараемся разобраться с этой проблемой.

Прочитав эту статью, вы почувствуете себя более уверенно в выборе цвета. А если у вас вообще нет чувства цвета, то это просто рекомендации по хорошим сочетаниям. Поговорим о распространённых цветовых ошибках, которые нас окружают повсеместно, и как их избежать.

Статья не поможет найти хорошие градиенты или оттенки. Она предназначена для подбора красивых, чётких цветов для различных категорий информации (например, континентов, отраслей промышленности, видов птиц) в линейных, круговых, полосковых диаграммах и так далее.


Визуализация категорий в FiveThirtyEight, у Надии Бремер, в Pudding, New York Times, The Economist и Akkurat

Содержание


  1. Вступление
  2. Расширьте своё понимание цветов
  3. Не танцуйте по всему цветовому кругу
  4. Используйте насыщенность и яркость, чтобы работали тона
  5. Используйте тёплые цвета и синий
  6. При использовании зелёного сделайте его жёлтым или синим
  7. Избегайте чистых цветов
  8. Избегайте ярких, насыщенных цветов
  9. Сочетайте цвета с разной яркостью
  10. Сделайте цвета одинаково красочными
  11. Избегайте слишком слабого контраста с фоном
  12. Избегайте слишком сильного контраста с фоном
  13. Выбирайте достаточно ненасыщенный фон
  14. Просто копируйте цвета или попробуйте их понять

Вступление


Я буду много говорить о насыщенности, яркости и тонах. Это цветовые пространства HSB (тон, насыщенность, яркость) или HSV (тон, насыщенность, значение):

  • Тон (hue) находится в диапазоне от 0 до 360, это ваш типичный цветовой круг:
  • Насыщенность (saturation) изменяется от 0% (серый) до 100% (супер-пупер красочный!!):
  • Яркость/значение (brightness/value) изменяется от 0% (чёрный) до 100% (фактический цвет):

Чтобы преобразовать цвета из HEX (например, #cc0000) или RGB (например, rgb(207, 176, 58)) в HSB/HSV, используйте такой инструмент, как colorizer.org.

Родственником HSB/HSV является цветовое пространство HCL. Там те же параметры (тон, цветность = насыщенность, яркость), но ближе к тому, как мы действительно видим цвета. Наш сервис Datawrapper использует цветовое пространство HCL в инструменте выбора цвета:



Поскольку в Adobe Photoshop или colorizer.org нет HCL, при каждом упоминании градусов (например, 0) или процентов здесь имеется в виду цветовое пространство HSB/HSV.

Хорошо, давайте начнём.

Расширьте своё понимание цветов




Вы можете подумать: Для диаграммы мне нужно пять цветов. Поэтому я использую зелёный, жёлтый, синий и красный. И хм может, оранжевый? Или фиолетовый!

Если вы не задумывались о цветах с тех пор, как ребёнком раскрашивали свою книжку-раскраску, то эта мысль имеет смысл. Поэтому я и пишу эту статью, чтобы рассказать вам, что цветов на самом деле больше.

Посмотрите на эту диаграмму и сравните её с основными цветами :


Кошки или собаки? Автор: Надия Бремер

На диаграмме цвета совсем другие. Надия используется красный , который отличается от обычного красного . Зелёный это можно ли его вообще назвать зелёным ?

Поэтому, прежде чем мы ввести правила, позвольте немного напугать вас: можно использовать буквально тысячи цветов. Есть жёлтоватый красный , синеватый красный и всё, что между ними. Есть серый , но есть также холодный серый и тёплый серый . А еще есть синий цвет. Так много синего! Как этот , этот , этот , этот и этот . И мы ещё не говорили об оранжевом и жёлтом.

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

Не танцуйте по всему цветовому кругу




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

В этот момент есть смысл посмотреть на цветовой круг. Для этого подходит Adobe Color или Color Calculator.


Color Calculator для выбора гармоничных сочетаний

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

Your browser does not support HTML5 video.

На видео я использую цветовой инструмент Paletton, начиная с тетрадного сочетания, а затем уменьшаю расстояние. Обратите внимание, насколько красивее становятся цветовые сочетания.

Если расстояние достаточно маленькое, вы в основном используете взаимодополнительные или дополнительные (complementary) цвета. И это отличный выбор! Множество дополнительных цветовых пар прекрасно работают вместе. Если сомневаетесь, всегда используйте дополнительные цвета и их соседей.

Итак, давайте сделаем это на этот раз с помощью Adobe Color:


Наши дополнительные цвета в Adobe Color

Наши цвета противоположны на цветовом круге, поэтому явно дополняют друг друга. Ура! Но они также непригодны: два оранжевых слишком похожи. И все выглядит так ярко.

Вот где нужно изменить насыщенность и яркость.

Используйте насыщенность и яркость, чтобы работали тона




Насыщенность и яркость так же важны, как и тон. На самом деле, вы можете создавать новые цвета просто изменяя насыщенность и яркость. Вот две пары цветов с одинаковым тоном, только разной насыщенностью и яркостью: / (если немного изменить тон, то результаты будут ещё лучше: /).

Вернёмся к нашей цветовой комбинации: . После игры с насыщенностью и яркостью она становится такой:


Более подходящие дополнительные цвета в Adobe Color

Я обесцветила светло-голубой и светло-оранжевый и сделала все цвета темнее, кроме светло-оранжевого. Чёрт возьми, с этим уже можно работать!

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

Вот что я сделала со всеми этими цветовыми палитрами: и и . Все они примерно дополняют друг друга и у всех разная насыщенность и светлость.

Используйте тёплые цвета и синий




Дизайнеры инфографики особенно любят ещё одно сочетание: жёлтый/оранжевый/красный и синий. Пролистайте, например, портфолио South China Morning Post или вот это от The Economist (PDF): они используют эти цвета гораздо чаще, чем какой-нибудь фиолетовый или зелёный.


Три страницы South China Morning Post

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

И они доступны: дальтоники легко отличают синий и оранжевый/красный.

Поэтому, если сомневаетесь, то используйте оранжевый/красный с синим.

При использовании зелёного сделайте его жёлтым или синим




Яркая зелень занимает шестую часть на цветовом круге, примерно с 90 до 150 , с пиком на 120 . Однако вы не найдёте хорошей инфографики с такими цветами. Почему?

Во-первых, зелёный сам по себе просто очень тёмный. А осветление зелени переходит в неуклюжий неон . Чтобы получить хороший тон, нужно сильно осветлить и обесцветить зелёный цвет больше, чем другие цвета. Это именно то, что Washington Post делает со своим зелёным здесь:


Как Трамп откатывает наследие Обамы, The Washington Post

Это 142 зелёный, но насыщенной только на 14%. Тот же тон с той же яркостью на 100% насыщенности: . Вот как.

И помните о дальтониках: чистый зелёный в сочетании с красным, оранжевым или коричневым им трудно различить.

Поэтому, когда вы используете зелёный, сделайте его немного жёлтым или немного синим. Вы можете увидеть это в примерах в начале статьи: у всех зелёных, кроме , тон больше 160 (то есть они голубее) или меньше 60 (то есть более жёлтые) . В этом проекте, который мы уже видели, Надия использует как жёлто-зеленый, так и сине-зелёный:


Кошки или собаки? Автор: Надия Бремер

Похоже, вы можете использовать их в инфографике как два разных цвета: беспроигрышный вариант!

Избегайте чистых цветов




Чистые тона расположены в цветовом круге точно на 60, 120, 180, 240, 300 или 360/0:



Вот пример: в HSV/HSB значение тона этого ярко-синего составляет 180, значение насыщенности 67%, а значение яркости 91%. Вы также можете посмотреть значения RGB вашего цвета: если хотя бы два значения совпадают, то цвет чистый. Например, наш это rgb(77, 232, 232).

Чтобы сделать цвета более естественными и приятными для глаз, можно либо изменить насыщенность чистых цветов, либо сделать их темнее. Если хотите яркие, насыщенные цвета, то выбирайте смешанные цвета, которые находятся по крайней мере на 5-10 от чистых.

На изображении выше у красного и оранжевого, синего и зелёного одинаковая насыщенность и светлость. Единственное различие тон: красный (0), синий (240) и зелёный (120) выглядят более сочными, чем оранжевый (40), средний синий (211) и синеватый зелёный (170).

Избегайте ярких, насыщенных цветов




Яркие цвета обязательно привлекут внимание читателей. Но эти читатели не скажут вам спасибо. Большинство немного напрягаются, когда видят такие цвета: очень насыщенные, яркие цвета НЕ будут уместны для серьёзного, доверительного или спокойного [общения], объясняют Бартрам, Патра и Стоун в своей статье Аффективный цвет в инфографике от 2017 года (PDF).

Если цвета приближаются к 100% насыщенности и 100% яркости, скорее всего, они слишком яркие. Это определённо относится к чистым цветам, таким как .

Но я видел раньше видел такие сумасшедшие цвета, и они выглядят хорошо, скажете вы и назовёте проекты вроде этих:


Статья New York Times о плейлистах


Статья Bloomberg о банкротствах


Статья Pudding о знаменитостях

Если сравнить цвета из этих примеров с , то они менее насыщенные или более тёмные. На 100% насыщенный и 100% ярко-зелёный цвет становится в New York Times менее насыщенным , а также менее насыщенным и тёмным в статье Bloomberg и в статье Pudding .

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

Всё это работает, потому что в Pudding, The New York Times и Bloomberg отличные дизайнеры. Если сомневаетесь, избегайте 100% насыщенности в сочетании со 100% яркостью.

Сочетайте цвета с разной яркостью




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

Например, на крайней левой диаграмме выглядят как в оттенках серого.

Чтобы избежать такой неприятной гаммы, есть два варианта:

  • Исправить в оттенках серого: изменить яркость каждой области, сделав некоторые цвета ярче, а некоторые темнее, например: . Так они выглядят в оттенках серого:
  • Разделить области, например, белой границей

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

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


Цветовые схемы Viridis

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

Сделайте цвета одинаково красочными




В своей инфографике вы часто хотите выделить цвета. Есть разные способы достичь этого. Цвета выделяются по следующим характеристикам:

  • потому что они намного темнее
  • потому что они намного светлее
  • потому что они более насыщенные
  • потому что они более чистые

Но обычно вы просто хотите выделить один или два цвета. Большинство остальных должны быть более или менее одинаково заметными.

Если вы используете цвета с различной яркостью (разные в оттенках серого), вам нужно их сбалансировать. Попробуйте обесцвечивать яркие цвета. Добавьте больше насыщенности в тёмные.

Или выберите менее чистый оттенок: на изображении выше зелёный и синий очень чистые, поэтому я их затемнила (вот как они выглядят со 100% яркостью: ).

Затем я хотела добавить красный но яркий красный слишком интенсивный как чистый оттенок (с 0) . Так что у меня было два варианта:

  1. просто затемнить его: .
  2. переместить оттенок (и только оттенок) на 30, чтобы сделать его более оранжевым .

Я выбрала второй, чтобы сделать его немного более дружелюбным. Но подходят оба варианта.

Избегайте слишком слабого контраста с фоном




В удивительно большом количестве инфографике на ярком фоне используются пастельные цвета. Они часто не очень насыщенные и ужасно светлые.

Это вызывает проблемы: если вы работаете с небольшими областями, линиями и точками, то светлые и ненасыщенные цвета трудно различимы. Но даже если разборчивость не является проблемой например, для больших областей то ваша инфографика должна нормально контрастировать с фоном, чтобы уверенно заявить: Эй, я здесь, и мне есть что сказать.

Вот что нужно делать, когда цвета слишком ненасыщенные и светлые :

  • Увеличьте насыщенность:
  • Сделайте их темнее:
  • Или сделайте и то, и другое для достижения наилучшего результата:

Конечно, это тоже дело вкуса. Но если вам кажется, что цвета слишком пастельные, просто попробуйте сделать их насыщеннее и темнее. Просто посмотрите, что получается. И если выходит хорошо, так и оставьте.

Избегайте слишком сильного контраста с фоном




Верно и обратное: не делайте цвета слишком тёмными и насыщенными на ярком фоне. Если сомневаетесь, попробуйте осветлить цвета, убрать немного насыщенности и посмотрите, что получается.

Выбирайте достаточно ненасыщенный фон




Когда вы разобрались с цветами, хорошей идеей может показаться красочный фон. Но у такого фона два больших недостатка: во-первых, он легко отвлекает от данных. Во-вторых, чрезвычайно ограничивает потенциальную цветовую палитру и поэтому с ним трудно работать. На самом деле, чем насыщеннее фон, тем он сложнее, так что лучше выбрать ненасыщенные цвета. Вот некоторые базовые правила для цветового пространства HSB/HSV:

  • Если нужен светлый фон, держитесь подальше от цветов с яркостью менее 95% и насыщенностью более 7%.
  • Если нужен тёмный фон, сохраняйте насыщенность меньше 20%. Кроме того, не уходите в полностью чёрный держите яркость между 10% и 25%.

Просто копируйте цвета или попробуйте их понять


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

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


Фото дерева niko photos на Unsplash

  • Выберите картинку с цветами, которые вы считаете красивыми, например, произведение искусства или фотографию природы. Затем выберите оттуда цвета с помощью пипетки, например, в Photoshop или image-color.com. Попробуйте применить их в своей следующей инфографике.
  • Установите Adobe Capture, который реализует ту же идею, но для живых изображений: он позволяет захватывать цвета из окружающего мира (удивительно, насколько ненасыщенные цвета вокруг нас!)
  • Поиграйте с ручным выбором цветов: посмотрите на экран. Какие цвета вы видите? Насколько они тёмные и насыщенные? Какие оттенки близки, какие противоположны на цветовом круге?
  • Выбирайте цвета из красивой инфографики. Измените некоторые из них. Они всё ещё хорошо сочетаются?

Кроме того, в следующий раз, когда создадите инфографику и будете недовольны цветами, проанализируйте их в цветовом пространстве HSV/HSB, например, с помощью colorizer.org:

  • Насколько цвета насыщены насколько они становятся лучше или хуже, если увеличить или уменьшить насыщенность на несколько (или на много) процентных пунктов?
  • Каково значение тона? Что произойдёт, если изменить тон всего на несколько градусов?
  • Яркость цветов отличается?

Со временем вы перейдёте с уровня Это прекрасно, но я не знаю почему на уровень Это прекрасно по определённой причине. И обнаружите, что способны нарушать всё больше и больше этих правил и по-прежнему создавать отличные цветовые комбинации.
Подробнее..

Формирование диаграммы телефонных звонков в SVG формате при помощи Excel

22.07.2020 10:16:05 | Автор: admin
В данной статье описывается, как с помощью программы Microsoft Excel обрабатывать информацию из детализации телефонных вызовов, получая на выходе векторную диаграмму, которая наглядно отражает данные телефонные вызовы во времени и по дням. Сама по себе данная диаграмма напоминает диаграмму Ганта, которая чаще всего применяется для иллюстрации плана работ по какому-либо проекту.

Диаграмма Ганта представляет собой совокупность горизонтальных полос на плоскости. Горизонтальное направление соответствует величине времени, и данная величина, в общем случае, может быть непрерывной. А в вертикальном направлении данная плоскость разбита на множество горизонтальных зон фиксированной ширины. Для классической диаграммы Ганта, отражающая график работ, каждая такая зона соответствует определённому виду работы (рис. 1). Полосы диаграммы изображаются в пределах данных зон. Полоса, изображённая в конкретной зоне, характеризует соответствующий данной зоне вид работы, а левая и правая границы полосы характеризуют соответственно время начала и конца данной работы. Следовательно, длина полосы характеризует продолжительность данной работы.


Рис. 1. Диаграмма Ганта для иллюстрации графика работ.

В случае с диаграммой телефонных звонков, описываемой в данной статье, зоны в вертикальном направлении будут характеризовать дни (сутки). При этом по горизонтали шкала времени диаграммы соответствует интервалу от 0 до 24 часов, протяжённостью в одни сутки. Каждая полоса на такой диаграмме будет соответствовать одному телефонному звонку. Левая и правая границы полосы время начала и конца вызова, а номер зоны (по вертикали) день, когда был произведён вызов. Диаграмма подобной конфигурации позволяет наглядно проиллюстрировать и оценить, насколько часто совершаются звонки, оценить их среднюю продолжительность, распределение по времени суток и т.д. Более того, к данной диаграмме можно добавить ещё одно свойство: цвет полосы. Раскрашивать полосы можно по разным признакам. Во-первых по типу вызова (входящий или исходящий). Во-вторых по телефонному номеру вызова. В первом случае достаточно двух цветов. Во втором гораздо больше, но, как правило, достаточно не более десятка цветов на самые популярные телефонные номера, фигурирующие в вызовах чаще всего. В данной статье описывается формирование диаграммы за период в пять календарных месяцев и с учётом наличия двух мобильных операторов (двухсимочного телефона). Цвета полос на диаграмме будут выбираться по признаку SIM1/SIM2 входящий/исходящий, то есть, потребуется четыре различных цвета.

Формирование диаграммы, в отличие от построения, предусматривает именно генерацию выходного файла с данной диаграммой. А что касается построения, то, как правило, построение диаграммы в Excel подразумевало бы соответствующую операцию именно в Excel одним из стандартных средств. Даже если такая операция и возможна (диаграмма Ганта), то она вряд ли будет удобной в отображении и масштабировании на больших объёмах входных данных. В случае с формированием файла векторного формата SVG с подобной диаграммой программа Excel применяется в качестве программного инструмента, где удобно работать с табличными данными. Вместо Excel можно было написать стороннюю отдельную программу и формировать SVG файл с помощью неё. Но Excel в данном случае я выбрал не случайно. Во-первых, в своём роде, имеется некая наглядность обработки информации, а во-вторых специфичность выходного формата SVG. Данный формат является форматом масштабируемой векторной графики и содержит внутри текстовые данные, форматированные по принципу XML. Это своеобразный язык разметки, содержащий определённый набор команд и параметров, характерные для рисования того или иного графического элемента. Команды, к примеру, могут быть такие: нарисовать линию, многоугольник, окружность, написать текст. А параметры координаты углов многоугольника, цвет заливки, размер и шрифт текста и т.д. По сути, зная язык разметки SVG, можно с помощью обычного текстового редактора (Блокнот) вручную создать ту или иную картинку из разряда простейших. SVG файлы для просмотра можно открыть любым распространённым Интернет браузером.

Прежде чем приступить к формированию SVG диаграммы, необходимо не только скачать детализации вызовов с сайтов мобильных операторов, но и предварительно их обработать. Как я уже отмечал, будут рассмотрены два мобильных оператора. Один из них Теле2, другой Мегафон. Детализация звонков Теле2, которую можно скачать в личном кабинете на соответствующем сайте, представляет собой PDF документ с большой таблицей, которая поделена на страницы (рис. 2).


Рис. 2. Вид детализации вызовов Теле2.

В случае с Мегафоном всё практически аналогично, за исключением, что детализация представлена в XLS (Excel) файле (рис. 3).


Рис. 3. Вид детализации вызовов Мегафон.

И ту, и другую детализацию необходимо по-разному обработать, отсеить лишнее и привести в порядок. Данный текст имеет некую регулярность, поэтому легко подвергается автоматической обработке. Её я производил в отдельном документе с помощью функций (формул) Excel. Думаю, что не стоит останавливаться подробно на данном вопросе. В результате такой обработки получилась аккуратная большая таблица с минимально необходимыми полями: дата, время, длительность, тип звонка, номер телефона, симкарта (рис. 4). Всего получилось 2102 записи телефонных вызовов. Кстати, на рисунке 3, где изображён лист Excel с исходным текстом детализации, можно видеть наличие других листов. Данные листы я добавил как раз для реализации промежуточных этапов обработки, как продолжение исходного документа.


Рис. 4. Смешанная детализация, приведённая в порядок.

Получившуюся таблицу я скопировал в новый документ на лист A, тут же дополнив её дополнительными полями: адрес цвета полосы, левая граница полосы (a) (в секундах от начала суток), правая граница полосы (b) (рис. 5).


Рис. 5. Дополнительные параметры на первом листе.

Данные поля легко рассчитываются при помощи формул Excel. Адрес цвета указывает на один из четырёх адресов ячеек конфигурационного листа C, в которых он прописан в HEX-RGB формате. На данном листе указаны не только цвета, но и все дополнительные параметры SVG документа: координаты, сдвиги, масштаб и т.д. (рис. 6).


Рис. 6. Лист с параметрами.

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

Забегая вперёд, диаграмма получилась размером 4420 на 1800 пикселей. На самом деле сложно говорить о пикселях в векторной графике, но в описании SVG формата присутствует дискретная система координат, отсчёты которой я называю пикселями. А вообще, даже исходя из аббревиатуры, данная графика масштабируемая. Как я уже писал, диаграмма будет отражать звонки за 5 месяцев, а именно с мая по сентябрь включительно. Если посчитать, это соответствует 153 суткам. Ровно столько должно быть зон для полос на диаграмме. Заранее я определился с масштабами. По вертикали я решил отвести 10 пикселей на одну зону. При этом ширина полосы в зоне будет 8 пикселей, (с зазором в один пиксель сверху и снизу). Величиной зазора (отступа) в ячейке B8 листа C можно регулировать ширину полос в зоне. Масштаб по горизонтали можно выбрать, в принципе, любой, однако имеет место быть практическая наглядность диаграммы, приемлемое соотношение её сторон и вместимость. В итоге я решил взять 3 пикселя за протяжённость одной минуты, или иными словами, 20 секунд на пиксель. Итого, активная область диаграммы имеет следующие размеры. По горизонтали: 24*60*3=4320; по вертикали: 153*10=1530. Слева на диаграмме напротив каждой зоны должно быть написано её название. Названия зон полностью соответствуют датам. Для этой цели я решил отвести место шириной 100 пикселей. Вверху над диаграммой желательно (для удобства) написать метки времени, хотя бы часы. А внизу под диаграммой будет располагаться гистограмма, про которую я писал выше, а также дополнительная информация. Для этих целей я отвёл 270 пикселей, округлив высоту всей диаграммы до 1800. Кроме всего сказанного, на диаграмме я решил отразить светлые горизонтальные линии между зонами (днями), чуть более тёмными между неделями, а чёрными между месяцами. Кроме горизонтальных линий присутствуют также и вертикальные, расставленные через каждый час для границ часов. И ещё одна немаловажная деталь. На левой границе каждой изображаемой цветной полосы будет изображаться чёрная метка её начала в виде квадратной открывающейся скобки. Это нужно для того, чтобы предотвратить слияние двух полос, которые могут соответствовать подряд идущим телефонным вызовам.

Основная обработка информации происходит на листе B (рис. 7). Там можно видеть кучу лишних промежуточных столбов, значения ячеек которых можно было рассчитать в уме или сразу же учесть в окончательной формуле. Это касается координат углов каждой полосы. Однако мне это всё показалось очень громоздким, что на первых порах можно было запутаться.


Рис. 7. Лист с основными расчётами.

В колонке A извлекается номер дня (зоны) из даты вызова. В колонке B время вызова в секундах от начала суток. Это такое же значение, что и в колонке I листа C. В колонке C округлённая в большую сторону продолжительность вызова в минутах. Здесь стоит сделать оговорку, для чего введена такая неточность. Казалось бы, нужно брать продолжительность вызова с точностью до 20 сек, то есть до одного пикселя диаграммы (исходя из принятого масштаба). Однако очевидно, что очень короткие полосы шириной в 1-2 пикселя будут плохо отображаться на диаграмме. Поэтому минимальная длина полосы будет соответствовать хотя бы как минимум трём пикселям. И вообще, длина любой полосы будет кратна трём. За счёт округления длительности вызова в большую сторону (с точностью до минуты) диаграмма будет слегка переполненной, по сравнению с реальной ситуацией, однако это переполнение весьма незначительное. В колонке D с помощью формулы ДВССЛ извлекается значение цвета из параметров (Лист C) по рассчитанному адресу на листе A. Далее рассчитываются координаты углов полосы. Как я уже писал, там много лишних промежуточных расчётов, но я не стал переделывать. В колонке U вычисляется наличие выделения и цвет окантовки полосы, если телефонный номер текущего вызова совпадает с одним из четырёх приведённых телефонных номеров для выделения (на листе C). Забыл выше написать о том, что в выделяемом вызове на соответствующую полосу накладывается не только метка, но и серый цвет окантовки полосы (этот цвет также можно поменять на листе с параметрами). В обычном случае полоса не имеет окантовки. Наконец, в следующих трёх колонках происходит окончательное формирование текста на языке разметки SVG графики. В данной статье я не буду рассматривать описание и синтаксис данного языка. На самом деле в этом нет ничего сложного, я разобрался за несколько минут. В столбце V формируется код, рисующий полосу с окантовкой.
Пример:
<path fill="#FF5050" stroke="#808080" d="M1598,51L1598,59L1601,59L1601,51L1598,51" style="stroke-width: 1px;" stroke-width="1" stroke-dasharray="0"></path>.
В столбце W код для левого края полосы.
Пример:
<path fill="none" stroke="black" d="M1599,52L1598,52L1598,58L1599,58" style="stroke-width: 1px;" stroke-width="1" stroke-dasharray="0"></path>.
В столбце X код для отображения текста метки (цифра 1, 2, 3 или 4) только для тех вызовов, где она нужна. Данная избирательность выполняется с помощью формулы ЕСЛИ(U2<>none;;).
Пример текста 3:
<text x="1601" y="58" style="text-anchor: middle; font-family: times; font-weight: bolder; font-size: 8px;" stroke="none" fill="black"><tspan>3</tspan></text>.
На рисунке 8 представлен скриншот этих трёх столбцов в очень маленьком масштабе, так как иначе продемонстрировать практически невозможно из-за громоздкости текста. Также видно, насколько громоздкой получается запись формулы СЦЕПИТЬ со всеми её аргументами.


Рис. 8. Столбцы с результатами основных расчётов.

На листе Надписи происходит формирование надписей над диаграммой (метки часов) и слева от диаграммы (даты) (рис. 9). В формулах прописаны параметры шрифтов: размер, стиль, цвет шрифта и окантовки. Основной акцент расчёта автозаполнение ячеек по датам и часам, расчёт координат положения текста через равномерный шаг.


Рис. 9. Лист, формирующий надписи.

На листе Границы формируются все вспомогательные линии диаграммы, служащие границами зон (дат) и часов. На рисунке 10 показан скриншот, где видно формирование горизонтальных линий по зонам. В первых двух столбцах номер зоны (начиная с нуля) и её относительная вертикальная координата. В третьем столбце формируется код для SVG, рисующий линии. Здесь в формировании кода применяется не только привычная формула СЦЕПИТЬ, но и две формулы ЕСЛИ, вложенные одна в другую. Это необходимо для реализации рисования линии трёх различных цветов, в зависимости от ситуации. Как писалось выше, чёрные линии отделяет месяцы, серые недели, а светло-серые дни. Последние два цвета задаются на листе C в ячейках B17 и C17. В аргументах формулы ЕСЛИ присутствуют формулы ДЕНЬ и ОСТАТ. Первая формула распознаёт число из даты, заданной в виде целого числа, которое получено путём смещения значений номера зоны (из первого столбца) на заранее подобранную константу 42491. В частности, производится проверка на равенство числа из даты с единицей, распознавая тем самым начало нового месяца. Формула ОСТАТ применяется для распознавания начала новой недели (классический алгоритм). Во втором аргументе данной формулы стоит число 7, так как в неделе 7 дней. В частности, производится сравнение остатка от деления со значением 1. Этим значением (от 0 до 6) можно регулировать смещение дней недели на диаграмме, и оно подобрано таким образом, чтобы было соответствие реальному календарю. После формирования горизонтальных линий формируются 25 вертикальных линий уже более простым способом (23 линии на каждый час и ещё две граничные).


Рис. 10. Лист, формирующий границы.

На листе Мелочи (рис. 11) прописаны формирования дополнительной информации о свойствах диаграммы. В столбцах B и C прописаны координаты смещения для каждого элемента.


Рис. 11. Лист, формирующий дополнительную информацию.

На вкладке Занятость формируется гистограмма распределения плотности звонков во времени (рис. 12). Она представляет собой набор вертикальных линий различных длин, плотно стоящих рядом друг с другом и расположенных прямо под диаграммой. Число таких линий соответствует числу элементов времени (по 20 сек.), а именно 24*60*3=4320.


Рис. 12. Лист, формирующий гистограмму плотности вызовов.

Длина линии (высота столбика гистограммы) в точности соответствует сумме занятых элементов времени по всем 153 дням. То есть, если на текущий элемент времени в текущем дне приходится телефонный вызов, то он учитывается в гистограмме. Такой числовой массив я рассчитывал с помощью отдельной простейшей программы на Си. С помощью ячеек Excel такой расчёт сделать невозможно из-за многомерности операций. Можно было воспользоваться VBA, поместив туда соответствующий программный код, но на тот момент времени я этим средством вообще не владел. Код программы для расчёта массива значений гистограммы приведён ниже.
#include <stdio.h>#include <windows.h>int main(){int a,b,n,c,k;int q[4320];for(n=0;n<4320;n++){q[n]=0;}FILE *f,*f1;f=fopen("ab.txt","r");f1=fopen("Out.txt","w");for(c=0;c<2102;c++){fscanf(f,"%i\t%i\n",&a,&b);for(k=a;k<b;k++){q[k/20]+=1;}}for(n=0;n<4320;n++){fprintf(f1,"%i\n",q[n]);}fclose(f);fclose(f1);system("PAUSE");return 0;}

Входными данными программы служит текстовый файл ab.txt. В данный файл скопированы два столбца из листа A значений секунд начала и конца каждого вызова (об этом я уже писал выше, см. рис. 5). Рассчитанные значения массива выводятся в выходной файл Out.txt. Алгоритм расчёта простой, поэтому описывать его не стоит. Данные из выходного файла копируются в столбец D на листе Занятость. Первые три столбца условные обозначения элементов интервалов времени и их номер. Столбец E те же значение гистограммы, но масштабированные в 5 раз с округлением до целой части. Это сделано для удобного размещения гистограммы, наглядности и исключения громоздкости. Кроме того, каждое значение смещено на единицу. Это нужно для псевдо прорисовки горизонтальной оси. Даже если значение гистограммы нулевое (что характерно для ночного времени суток), один пиксель гистограммы всё равно будет изображён. Таким образом, будет прорисована ось абсцисс.

Наконец, на листе Результат объединены все сформированные коды SVG по каждому листу документа в определённом порядке (надписи и границы в первую очередь). Данное объединение я произвёл при помощи обычного копирования столбцов вручную (рис. 13). При необходимости можно написать в VBA функцию автоматического экспорта SVG файла, пробегаясь по результирующим столбцам всех листов. В самой первой строке сформирован заголовок файла. В нём указаны, прежде всего, ширина и высота картинки. Самая последняя строка, дописанная вручную, закрывает документ, точнее главный блок svg. Всего получилось около 6800 строк.


Рис. 13. Лист с объединением результатов.

Затем нужно скопировать всё содержимое этого листа в текстовый редактор (я пользовался программой AkelPad) и сохранить документ в файл с расширением svg в кодировке UTF-8. После этого, при отсутствии ошибок, файл открывается в Интернет браузере для просмотра. На рисунках ниже приведены виды различных участков получившейся картинки с различными масштабами.


Рис. 14. Общий вид получившейся диаграммы в Chrome.


Рис. 15. Левый верхний угол диаграммы (виды различных границ и названия зон).


Рис. 16. Полосы диаграммы с метками.


Рис. 17. Полосы диаграммы и гистограмма под ними.


Рис. 18. Дополнительная информация на диаграмме.


Рис. 19. Полосы диаграммы и метки часов над ними.

Подробнее..

Сколько зарабатывает Аналитик данных обзор зарплат и вакансий в России и за рубежом в 2020

25.09.2020 20:20:19 | Автор: admin

Привет, Хабр! 28 сентября, Skillfactory запускает новый поток курса Data Analyst, поэтому мы решили сделать широкий обзор рынка вакансий, которые предлагают сегодня компании.

Действительно ли профессия аналитика данных может приносить до 300к/наносек? Какие умения требуют работодатели от аналитиков и что вообще нужно знать, чтобы стать востребованным и высокооплачиваемым спецом? Какие возможности для роста предлагает рынок сегодня?

Мы проанализировали 450 вакансий на должность аналитика данных в России и за рубежом и собрали результаты в этой статье.

Кто такой аналитик данных и что он должен знать


Прежде чем анализировать вакансии, разберемся, что делает Data Analyst в компании. В IT-сфере есть три направления специальностей по работе с данными: Data Analyst, Data Engineer и Data Scientist.

Data Analyst собирает информацию, обрабатывает ее и интерпретирует ее на человеческий язык. По сути, он переводит статистику и big data в понятные и наглядные выводы, которые можно использовать для развития конкретного проекта или бизнеса в целом.

Результат работы аналитика данных это основа для принятия любых бизнес-решений.

Data Engineer работает больше не с самими данными, а с их инфраструктурой: базами данных, хранилищами и системами обработки. Инженер данных определяет, как анализировать данные, чтобы они были полезными для проекта. Если обобщить, то Data Engineer налаживает конвейер обработки данных.

Data Scientist занимается стратегической работой с информацией. Именно он создает системы прогнозирования, моделирования и динамического анализа, внедряет алгоритмы автоматизации и обучения.

Главная сложность в том, что границы между этими тремя специальностями довольно размыты. Большинство компаний не видят разницы, поэтому часто в вакансиях Data Analyst встречаются требования, которые больше подходят специалистам Data Engineer или Data Scientist.

В основном это обусловлено спецификой рынка. Если в IT-компаниях знают, что Data Analyst, Data Engineer и Data Scientist это в идеале три разных специалиста или даже три разных подразделения, то в продуктовых компаниях и производствах часто об этом даже не задумываются.

Что требуют работодатели от аналитика данных


Мы проанализировали свыше 450 вакансий на позицию аналитика данных, открытых в августе-сентябре 2020 года.

Во многих случаях требования к специалистам очень отличаются. Как мы писали выше, границы между Data Analyst, Data Engineer и Data Scientist стерты, поэтому часто бывает, что в заголовке вакансии пишут Аналитик данных, а фактически вакансия полностью соответствует Инженеру данных.

Но мы смогли выделить набор хард и софт скилов, которые работодатели указывают в большинстве вакансий на должность аналитика данных.

Хард скилы


Python с библиотеками для анализа данных Pandas и NumPy. Это мастхэв, его знание хотя бы на базовом уровне требуют 83% компаний в отрасли. Знание R, JavaScript и других ЯП требуют нужны всего лишь 17% работодателям.

Интересно, что в 2013 году по результатам опроса Data Analyst и Data Scientist язык R в аналитике данных был куда популярнее его использовали 61% специалистов.

SQL практически во всех вакансиях требуется знание SQL и навыки работы с реляционными базами данных. Чаще всего требуют умение писать запросы и оптимизировать их.

Навыки работы с NoSQL системами управления базами данных вроде MongoDB, CouchDB или Apache Cassandra работодатели требуют довольно редко примерно в 9% вакансий.

Power BI, Qlik, Tableau. Большинство компаний не требует знаний какой-нибудь конкретной программы визуализации данных. Обычно они указывают одну из трех на выбор или пишут системы визуализации данных без указания конкретной.

В целом специалисты могут сами выбирать, что именно им удобнее использовать. Принципиальной позиции у абсолютного большинства работодателей нет.

Опыт работы с Agile, Scrum, Kanban. Почти в половине вакансий работодатели указывают, что дополнительным плюсом будет умение соискателя работать с гибкими методологиями создания продуктов.

То есть, важно не только то, что делает аналитик данных в рамках своей специальности, но и то, как он это делает.

Но несмотря на то что многие указывают это в вакансии, ключевым требованием опыт работы с Agile не является. Да, соискателю придется потратить время, чтобы привыкнуть работать в таком формате, но, по мнению компаний, это не критично.

Excel и Google Sheets. Как ни странно, но в трети вакансий требуется знание электронных таблиц. В основном это нужно продуктовым и консалтинговым компаниям, которые довольно слабо пересекаются с диджитал-разработкой, или же относительно небольшим проектам, где весь отдел аналитики состоит из нескольких человек.

Действительно, маленьким командам часто незачем использовать мощные ресурсы SQL, если для обработки данных вполне хватает и обычного Excel. Но нужно понимать, что в таких ситуациях аналитик данных часто занимается сразу всем: сбором и анализом данных, инфраструктурой и автоматизацией.

Многие компании отдельно выделяют высокий уровень математической подготовки. Но здесь нужно понимать, что Data Analyst, в отличие от Data Scientist, использует довольно ограниченные математические инструменты, поэтому не нужно быть гением математики. Большинство задач аналитика данных вписываются в рамки базовых знаний статистики, теории вероятностей, математического анализа и линейной алгебры.

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

По основным хард скилам это все. Остальные встречаются реже, чем в 10% вакансий, поэтому их можно списать на индивидуальные особенности работы в отдельных компаниях.

Софт скиллы


В целом они практически совпадают для всех специальностей, которые работают с данными:

  • Критическое мышление
  • Аналитический склад ума
  • Умение правильно излагать и доносить информацию
  • Ответственность и внимание к деталям
  • Бизнес-мышление
  • Готовность принимать решения и брать ответственность за результат
  • Многозадачность
  • Чувство юмора

Интересно то, что многие считают профессию аналитика данных малообщительной. Аналитик кажется нердом, который работает только с цифрами, а не с людьми.

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

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

Обязательный английский часто приятно отражается на зарплате. Вакансии, которые предлагают работу на международных проектах, гарантируют денежную компенсацию в 1,3-2 раза больше, чем русскоязычные.

Зарплата и другие плюшки для аналитика данных


Теперь перейдем к самому интересному к зарплате. Мы проанализировали открытые вакансии на сайтах HH.ru и Хабр Карьера.

Больше всего вакансий для аналитиков данных по состоянию на 12.09.2020 открыто в Москве (241) и в Санкт-Петербурге (74). Для сравнения, во всей остальной России актуально всего 99 вакансий на эту должность.

Интересно, что только 20% компаний указывают уровень заработной платы в самом объявлении. Остальные 80% предпочитают обсуждать денежное вознаграждение в личной беседе с соискателем.

Разброс зарплат довольно большой. Зависит он не только от опыта соискателя, но и от географии. К примеру, аналитик-стажер в Перми получает 25 000 рублей, а Data Analyst в московском офисе международной компании зарабатывает 200 000 рублей.

В Москве средняя зарплата аналитика данных составляет 134 000 рублей. На нее вполне может рассчитывать хороший специалист с опытом от 2 лет.

Стажеры и Junior-спецы получают от 60 000 рублей. Есть небольшое количество вакансий, которые предлагают ниже этой суммы (8%), но они в основном предлагают работу не на полный день либо с ограниченной загрузкой в неделю.



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

Руководители отделов аналитики и Senior-спецы могут рассчитывать на зарплату от 170 000 рублей. Есть даже вакансии, которые предлагают больше 250 000 рублей в месяц. Да, для них требуется опыт больше 5 лет в аналитике и большой пул компетенций, но такие вакансии есть. Так что вполне ясно, куда можно расти.

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

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

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

Аналитики данных востребованы в любом крупном и среднем бизнесе, особенно в тех проектах, которые относятся к диджитал и IT. Финтех-банки, диджитал-агентства, продуктовые компании, которые налаживают онлайн-систему продаж, консалтинговые проекты.

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

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

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

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

Мы также провели сравнительный анализ вакансий из Украины и Беларуси.

Средняя зарплата аналитика данных в Украине порядка 20 000 гривен (53 000 рублей). В столице есть вакансии с оплатой в 2-2,5 раза выше, но их выставляют преимущественно международные компании с филиалами в Киеве.

Абсолютно та же ситуация и в Беларуси. Средние размер заработной платы аналитика данных составляет 2800 белорусских рублей (81 000 рублей), Но разброс зарплат очень большой. В Гомеле, к примеру, аналитик с опытом от года получает в среднем 1100 белорусских рублей (31 000 российских рублей), а в Минске специалист может зарабатывать вплоть до 10 000 (287 000 российских рублей).

Откуда прийти в профессию и куда расти аналитику данных


Есть мнение, что попасть в касту аналитиков можно только с исключительными знаниями математики. Но это не так.

В аналитику обычно уходят Junior- и Middle-разработчики на Python. Если вдобавок есть базовые знания SQL вообще отлично. В таком случае разобраться со всеми особенностями работы будет намного проще.

Также можно начать карьеру непосредственно с аналитика. Выбирайте один из десятков доступных курсов и вперед. Высшую математику знать необязательно. Для Data Analyst уровня Junior и Middle нужно только знание инструментов работы с данными. А в большинстве случаев хватит и школьных знаний математики.

Возможностей роста для специалиста аналитики данных тоже хватает. Три самых очевидных: Data Mining Specialist, Data Engineer, Data Scientist. Первый работает непосредственно с поиском данных для аналитики, второй разрабатывает инфраструктуры данных, а третий прогнозированием и стратегией.

Еще один возможный вариант BI-аналитика. Визуализация данных аналитики это отдельный скил, и многие крупные компании ценят сотрудников, которые умеют не только анализировать информацию, но и доходчиво предоставить выводы руководству.

Специально для материала, мы попросили дать комментарий о необходимых навыках для роста в BI-аналитике,Александра Царёва, основателя компании SmartDataLab, лидера образовательного курса BI SkillFactory и Сергея Земскова руководителя направления Power BI/DWH SmartDataLab и преподавателя Bootcamp SkillFactory.

В обзоре указаны мастхэв компетенции, но если вы хотите и дальше расти как Аналитик данных, вам понадобится быть в курсе ETL и изучить:
Так называемый золотой треугольник Microsoft: SSRS, SSIS, SSAS;
Иметь представление о других промышленных ETL, например, KNIME;
Литературу по архитектуре данных, например, книгу Билла Инмона Методология Кимбалла;
Также нужно хотя бы в первом приближении понимать, что такое Informatica, GreenPlum, Pentaho, чем они друг от друга отличаются и как работают.
Быть в курсе, что такое SAP Web Analytics и другие новые BI решения от SAP, хотя сейчас отмечается переход с этих решений на Power BI (который, по исследованию проведенному в июле-августе телеграм каналом вакансий и фриланса в BI/DWH BI HeadHunter, в топе по запросу от работодателей).

Это солидный пласт знаний, но он сделает вас уберспецом.

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

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

В вакансиях на сайтах работы часто смешивают понятия. Даже встречаются предложения вроде Бизнес/системный аналитик. Не надо так. Это два разных направления.

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

Аналитик данных это перспективная и востребованная профессия. И чтобы стать Data Analyst, не нужно быть Перельманом и уметь решать теорему Пуанкаре хватит школьных знаний математики и упорства в освоении инструментов аналитика.

Совсем недавно мы запустили первый в России Онлайн-буткемп по Data Analytics, включающий в себя 5 недель обучения, 5 проектов в портфолио, оплачиваемая стажировка для лучшего выпускника. Это суперинтенсивный формат для самых целеустремленных: учиться нужно фултайм. Зато в итоге выход на работу уже через 13 месяца.

image

Узнайте подробности, как получить востребованную профессию с нуля или Level Up по навыкам и зарплате, пройдя онлайн-курсы SkillFactory:



Подробнее..

Коротко рынок труда в разработке после Covid

18.08.2020 10:04:18 | Автор: admin
Что происходит на рынке труда спустя полгода с начала локдауна, какие отрасли восстанавливаются, сколько вакансий открыто для разработчиков? Под катом посмотрим на реакцию ИТ-сферы на ковидную весну, сравним июль прошлого года с нынешним по количеству вакансий и узнаем о зарплатах. Обзор максимально сжатый, в 10 минут уложимся.



Сперва расскажу про общий рынок, для фона. Когда все пошло вниз мы понимали, что скоро окажемся там же. И оказались. Ниже график, где 6-я неделя года принята за 0% (3.02.2020). Заканчивается на 16-ой неделе (04.05.2020).

Динамика спроса на рынке труда в первые месяцы самоизоляции




Число публикуемых вакансий в Москве упало более чем наполовину к середине мая. Для примера, в начале февраля за неделю публиковалось ~ 125К вакансий, на 19-й неделе мая было опубликовано всего 50К. График наглядно показывает, как рынок труда реагирует на майские праздники вместе с самоизоляцией.

Теперь про ИТ. Здесь посчитал ТОП-10 запросов от соискателей для поиска вакансий. Только тех соискателей, у которых есть резюме в профобласти Информационные технологии, интернет, телеком. В этой профобласти резюме размещают не только разработчики, но также проджекты, аналитики, контент-менеджеры, smm-специалисты (в резюме можно указывать до трех профобластей).Что еще важно знать про график:
  • доля каждого запроса подсчитана доля от общего количества запросов от ИТ-специалистов за месяц;
  • запросы по синтаксису не объединял. Для примера, руководитель и руководитель проекта здесь разные запросы. Первый попал в топ-10 в апреле 2019, второй на 20-м месте
  • считал не фактическое кол-во запросов, а кол-во уникальных залогиненных пользователей, которые эти запросы делали.

Апрель 2019 года мы прекрасно проводили время, о вирусах говорил только Гейтс, а я планировал поездки по миру на год вперед. Ребята из ИТ искали вакансии с Java, Python, что-то для программиста. От апреля к июню 2019 изменения в топе в рамках погрешности. Но в апреле 2020 бам! курьер на первом месте. А вместе с ним удаленная работа, работа на дому и работа с ежедневной оплатой вытеснили из топа даже php. К июню 2020 все довольно быстро вернулось в норму.

Популярные поисковые запросы от специалистов сферы ИТ




Для большего понимания общей картины скажу, что количество запросов к поиску в апреле 2020 упало на 44% YoY (year-over-year), а июль 2020 к тому же месяцу предыдущего года вырос 18%. V-образный отскок, скажете вы? И окажетесь правы! Ниже рынок в целом в 2019 году в сравнении с текущим. 6-я неделя снова за 0%.

Спрос на общем рынке, вся Россия




Чтобы вас не сильно пугало падение на первом графике, привожу сравнение по годам на нем видим, что в мае спрос немного падает по естественным причинам (праздники, отпуска). Итак, вроде все ок, и регионы с Петербургом уже вышли на уровень на 2019, но Москва по-прежнему отстает. Думаю, это вопрос времени, если все пойдет, как идет.

Спрос в ИТ, вся Россия




На следующем графике количество вакансий по языкам программирования.
Список языков под спойлером
1C
Assembler
Bash
C
C#
C++
Delphi
Erlang /Elixir
Golang
Groovy
Java
JavaScript
Kotlin
Lua
Matlab
Objective-C
OpenGL
Pascal
Perl
PHP
PL/SQL
Python
R
Ruby
Rust
Scala
SQL
Swift
TypeScript
Visual Basic
Visual Basic.NET
Angular
Ember
JQuery
React
Vue
Искал упоминания по всему тексту вакансий: в названиях, описаниях, ключевых навыках. Этот подход не срабатывает, когда встречаются описания вида: Мы перешли с php на Java и теперь ищем разработчика на Java. Вакансия с таким описанием попадет в статистику и по php, и по java. Но, к счастью, таких кейсов не слишком много, чтобы исказить общую картину.Смотрел по июлю 2019 и по июлю 2020, по всей России. Топ-20 языков по количеству вакансий.

Количество вакансий по языкам программирования




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

Изменение количества вакансий по отношению к предыдущему году




По приросту все стандартно Kotlin и Go прирастают каждый год. Matlab растет на фоне общего спроса на работу с данными, а все остальное, видимо, действительно приросло за счет отложенного спроса и наших маркетинговых активностей.
Отдельно по фреймворкам JS метода та же самая, количество вакансий с упоминанием. Июль к июлю по всей России.

Количество вакансий с упоминанием фреймворков JS




Vue и React приросли на 58% и 41% соответственно. Jquery упал в рамках погрешности. Суммарно можно сказать, что вакансий сейчас точно не меньше, чем летом прошлого года. Если вы думали сменить работу, то, возможно, сейчас оптимальное время для этого, т.к. что будет осенью мы не знаем.

Далее зарплаты по тем же вакансиям. Нужно иметь в виду, что за одно лишь знание SQL платить 98к будут не всегда, т.к. в выборку по SQL также попадали вакансии с описанием вида SQL на хорошем уровне; Python: Pandas, Numpy, Matplotlib,....

Предлагаемые зарплаты по языкам программирования




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

Количество резюме по языкам программирования (упоминания в любом поле)




Топ-20 по количеству. Упоминания 1С искал только со словами разработчик или синонимами. Go не вошел в первую двадцатку, если считать упоминания в любом поле резюме, но далее график с упоминаниями только в названиях.

Количество резюме по языкам программирования (упоминания в названии)




Здесь Golang в первой десятке.
И далее ожидаемые зарплаты. На графике добавляю медиану, т.к. само по себе неустойчивое среднее еще более неустойчиво на данных из резюме. Считал по резюме, собранным по упоминаниям в любом поле. По всей России.

Ожидаемые зарплаты по языкам программирования




Здесь также топ-20. JS и php не перевалили за сотню, python не дотянул до топа совсем чуть-чуть.

Резюмируя: спрос на ИТ-рынке высок как никогда если вы планировали менять работу, то сейчас хорошее время. Если планировали найти сейчас у вас наиболее высокие шансы за последние полгода.На этом все. Если какой-то язык программирования отсутствует в обзоре, пишите в комментарии посмотрим на него отдельно.

P.S. Будет круто, если вы посмотрите наш опрос для специалистов ИТ-сферы.

Следующей статьей опубликую результаты опроса, когда наберем 1000 ответов с Хабра)
Подробнее..

Исследование технобренда hh.ru

14.10.2020 08:21:27 | Автор: admin
Всем привет! Недавно мы провели исследование технобренда hh.ru и решили поделиться его результатами. У нас стояла задача выяснить, насколько популярен hh среди аудитории ИТ-специалистов как потенциальный работодатель. Но поскольку себя нужно с чем-то сравнивать в исследовании также спрашивали про ряд других компаний на рынке. Под катом получился некий helicopter view на рынок труда в ИТ.




Что мы сделали


Опросили 1665 ИТ-специалистов, чтобы узнать:

  • на что обращают внимание при выборе работодателя;
  • условия работы в каких компаниях известны;
  • в каких компаниях хотят работать.

Основные поинты исследования


Методология: онлайн-опрос (CAWI).

Самый простой и привычный для аудитории вариант сбора мнений. Вопросы, варианты ответов, снова вопросы и так примерно 2-4 минуты на весь опрос. Облегченную версию анкеты можно посмотреть здесь.

Площадки опроса: hh.ru и habr.com

hh.ru основной источник респондентов (1352 завершенных ответа). Опрос был доступен на странице откликов. Блок с опросом показывался только тем соискателям, чье резюме размещено в профобласти Информационные технологии, интернет, телеком.

habr.com ответов получили существенно меньше (304), но такая диверсификация источников нам необходима ввиду того, что респонденты с hh.ru, используя наш сервис, уже в какой-то степени лояльны к бренду и их ответы могут быть смещены в пользу выбора hh. Респондентов в опрос приглашали в этой статье.

Еще 9 респондентов пришли из fb, отдельно их выносить не будем.

Как формировался список компаний

Сравнивались с компаниями, использующими схожий с нашим стек технологий. Некоторые известные компании не включили, т.к. приходилось ограничивать себя в количестве вариантов ответов чем больше компаний в вопросе, тем чаще респонденты уходят из опроса или отвечают случайным образом.

Данные в динамике

Да, мы проводим это исследование с 2018 года. Но каждый год есть пара отличий:

  • в 2018 году использовали только hh, поэтому данных по habr за этот год в статье не будет.
  • каждый год мы обновляем список компаний, поэтому на некоторых графиках в динамике у компаний может быть 0 (ноль) это означает, что их в году исследования не было.

Все правила соблюдены

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

Зачем мы это сделали

Наверное, это главный вопрос.

Каждый год, каждый месяц коллеги в HR-департаменте hh проделывают существенную работу, чтобы рассказать аудитории потенциальных сотрудников о том, как классно у нас работать. Год от года ребята пробуют разные способы, подходы и бюджеты эффект от всех активностей нужно измерять для правильных выводов и дальнейшего планирования.

Более глобально чем лучше наш технобренд, выше узнаваемость и желание работать в компании, тем дешевле обходится наём, быстрее закрываются вакансии, сотрудники дольше работают в компании. Эта статья тоже в какой-то степени работает на технобренд, именно поэтому она здесь. А также потому, что исследование действительно кажется полезным.

Чего нет в этой статье

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

Также в статье мы воздержались от размышлений и выводов. Только описательные сентенции, чтобы оставаться объективными.

Портрет аудитории


Портрет здесь для представления о том, кто отвечал на вопросы регионы, грейды и специализации респондентов. Если захотите посмотреть на какой-либо вопрос в разрезе должности или ещё чего-то напишите, добавлю в комменты.

Распределение респондентов по регионам




Графики в основной части статьи будут по всей России без деления на регионы.

Распределение по уровню позиции




Для общего представления о структуре респондентов. В статье мы также не станем делить по грейдам.

По специализациям




Здесь нужно заметить, что респонденты, отметившие вариант Моя деятельность не связана с ИТ не отвечали на вопросы анкеты, а сразу переходили к завершению опроса, т.к. не являются целевой аудиторией. Сами специализации брали из опроса stack overflow 2018 года, добавив к ним project manager.

По языкам программирования




Вопрос по языкам программирования задавался только тем респондентам, которые отметили, что занимаются разработкой (backend / frontend / fullstack / mobile)

Портрет QA




Эти вопросы задавали только тем, кто занимается тестированием. Варианты ответов собирали отталкиваясь от рынка и нашей специфики.

Портрет системного администратора




И здесь, аналогично предыдущим графикам, вопрос задавался только системным администраторам. Такие вопросы задаем, чтобы точнее определить свою ЦА и смотреть только на неё.

Как устроились на последнее место работы




Для общего представления о различиях в подходах к поиску работы смотрим на лояльность к hh среди пользователей Хабра и заодно смотрим на рейт по использованию hh.

Идеальный работодатель


Что предлагает ваш идеальный работодатель:




Зарплата, атмосфера и команда профессионалов рецепт успешного бренда, это можно сразу забирать на свои карьерные страницы. Здесь любопытно, что вариант востребованность продукта / популярность компании не входит в первый десяток качеств идеального работодателя.
Также стоит заметить, что этот вопрос задавался всем респондентам ИТ-специальностей, поэтому пункт Обязательное ревью кода проигрывает из-за неприменимости к большей части респондентов.

Идеальный работодатель в разрезе hh и Хабра




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

Известность условий работы


Дальнейшие вопросы подразумевали, что респондент знает о внутренней кухне компании, что-то слышал на конференциях или от знакомых. Нам нужно было понять, насколько хорошо нам удается доносить предметную информацию о hh до широкой аудитории в сравнения с компаниями, конкурирующими с нами за сотрудников.

Какие из перечисленных ниже компаний вам известны с точки зрения условий работы?




Наконец-то мы подобрались к самым интересным слайдам. Яндекс традиционно в топе, а вот Сбербанк (опрос проводили еще до ребрендинга, конечно же, это Сбер) обошел Mail.ru и Тинькофф со значительным отрывом, что, наверное, можно объяснить величиной штата.

Известность в разрезе hh и Хабра




Пришло время рассказать, что означает подпись Кроме ИТ-специализаций, не представленных в hh.ru из анализа в таких вопросах исключены специализации, которых нет в hh (как в компании-работодателе), а также на представителей которых намеренно не распространяется наша технобрендовая активность. К таким относятся:

  • Desktop or enterprise applications developer
  • Educator or academic researcher
  • Embedded applications or devices developer
  • Game or graphics developer

Также из выборок по эти вопросам исключены маркетологи и системные администраторы ввиду различий в специфике работы.

Известность в динамике Хабр




В 2019 году мы собрали гораздо больше ответов с Хабра, т.к. особенно не парились и просто сделали статью, где не было ничего, кроме ссылки на опрос. Это хорошо сказалось на количестве ответов, но плохо на нашей карме, поэтому в этот раз первым решили пожертвовать.

Известность в динамике hh




Aliexpress, Joom, Работа.ру, Revolut и ВТБ добавились только в 2020 году, эти объясняются их нулевые значения. В то же время нам пришлось исключить 2GIS, IBS и роботов, чтобы все поместились.

Желание работать в компаниях


В этом вопросе мы снимаем привлекательность бренда условно, насколько выше вероятность того, что вы откроете вакансию той или иной компании, или чьему рекрутеру больше обрадуетесь.

В каких компаниях вы хотели бы работать?




Первые позиции практически не изменились, но в топ-4 появляется JetBrains. Об условиях работы у ребят знал только каждый десятый, а вот работать хочет почти каждый третий. Видимо, востребованность продукта компании-работодателя все-таки важный поинт, хотя вероятно не он один.

Желание работать в компаниях в разрезе hh и Хабра




Просто посмотрите сами, очень интересно. И отличия респондентов hh и Хабра, и само ранжирование.

Желание работать в динамике Хабр




Стало значительно меньше респондентов, не желающих работать ни в одной компании.

Желание в динамике hh




Это последний слайд нашего марафона. Надеюсь, получилось рассмотреть графики и цифры на мобилках.

Заключение


Если появятся вопросы по методологии или интерпретации велкам.
Подробнее..

OZON подсчитал какие подарки не хотят получать на 14 февраля. Мы проанализировали спрос и узнали, что россиянам подарят

12.02.2021 08:05:33 | Автор: admin

Сегодня OZON опубликовал данные опроса среди покупателей, посвященного дню всех влюбленных. Маркетплейс опросил несколько тысяч человек от 18 до 45 лет, проживающих в городах-миллионниках. Главный вывод - Валентина помнят, а родных - любят. 73% ответили, что будут отмечать 14 февраля. Еще во время опроса OZON не постеснялся уточнить какие подарки влюбленные считают ужасными. Мы проанализировали спрос на эти товары и узнали скольким придется смириться с носками и гелем для душа.

Судя по данным OZON, самыми чудовищными подарками на День все влюблённых считаются валентинки, мягкие игрушки, открытки, гели для душа, тапочки и одежда, а также сладости и конфеты. Статистику ответов пока можете рассмотреть сами, а мы еще не раз к ней вернемся.

Неудачные подарки ко Дню всех влюблённых по мнению покупателей OZON:

- 18% опрошенных не хотели бы получить в качестве сюрприза валентинки, цветы, мягкие игрушки и носки;

- 10% респондентов не в восторге от конфет и сладостей;

- 5% ответивших против одежды и тапочек в качестве подарка;

- меньше всего - 4% опрошенных - отрицают гели для душа и дезодоранты в качестве презента.

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

Анализ спроса и выручки мы провели взяв за основу данные маркетплейса OZON. Площадка проводила опрос среди своих покупателей и будет правильным оценивать их поведение. Для сбора статистики мы использовали сервис аналитики маркетплейсов SellerFox.

Купаемся в деньгах

Возвращаемся от слов к делу. Изучаем данные категории Гели для душа. В 4% ответов респонденты заявили OZON, что не хотят получать такой подарок на 14 февраля. Мы тоже не хотели бы, но график подсказывает, что выбирать не придется. С начала января кривые спроса и выручки стремиться вверх.Продажи просели лишь однажды, когда продавцы резко подняли цены. Уверены, в скором будущем, большие цены трансформируются в гигантские скидки.

данные сервиса аналитики SellerFox в категории "Гели для душа" маркетплейса OZON, период с 12.01 - 11.02.2021данные сервиса аналитики SellerFox в категории "Гели для душа" маркетплейса OZON, период с 12.01 - 11.02.2021

В начале января дневная выручка от продажи гелей для душа составляла 500-600 тысяч рублей, а сегодня приблизилась к 1 000 000 рублей. За неделю с 4 по 9 февраля категория принесла селллерам почти 4 миллиона рублей.

данные сервиса аналитики SellerFox в категории "Гели для душа" маркетплейса OZON, период с 04.02-11.02.2021данные сервиса аналитики SellerFox в категории "Гели для душа" маркетплейса OZON, период с 04.02-11.02.2021

Если интересно, какой продавец заработал на гелях для душа больше, знайте - это сам OZON. За месяц площадка получила от продажи таких товаров 7 733 534 рубля. Из них почти 2 миллиона маркетплейс сделал за последние 7 дней - в 2 раза больше, чем доход от аналогичных товаров в первую неделю января.

данные сервиса аналитики SellerFox в категории "Гели для душа" OZON, срез по продавцам, период с 12.01-11.02.21данные сервиса аналитики SellerFox в категории "Гели для душа" OZON, срез по продавцам, период с 12.01-11.02.21

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

самый популярный товар на OZON в категории "Гели для душа" OZON, период с 12.01-11.02, данные SellerFoxсамый популярный товар на OZON в категории "Гели для душа" OZON, период с 12.01-11.02, данные SellerFox

Штопаем дырки в бюджете

Вернемся к мнению покупателей. Около 18% опрошенных заявили OZON, что не считают носки достойным подарком для признания в любви. Сколько в этой цифре кроется мужчин и женщин? Такую информацию мы пока не анализировали, зато собрали статистику по спросу и выручке в категории "Носки". Для начала посмотрели на данные более очевидного сегмента, который является вложением в категорию "Мужская одежда". Всматриваемся в мужские носки.

В январе спрос и выручка в этой категории также падает лишь однажды, когда средняя цена товара взлетает. Во всё остальное время носки приносят селлерам деньги - дневная выручка крутится около цифры в 1 млн. рублей. Если присмотреться к кривым, видим, что на этой неделе продажи в категории возросли. Это те самые нежеланные подарки ко дню всех влюбленных?

На самом деле, два миллиона в день на носках - это не шутки, а наглядная статистика. А еще посмотрите - в этой гонке OZON не добрался до первого места и заработал за месяц лишь 1 531 806 рублей. У лидера в кошельке оказалось 12 574 064 рубля.

Кстати, топ товаров среди мужских носков выглядит объяснимо. Посмотрите: покупатели отдают предпочтение комплектам товаров. Да, пусть такие носки стоят от 2 до 6 тысяч рублей, зато штопать их точно не нужно. Будем считать, что так выглядят "народные" инвестиции.

Если с мужскими носками все понятно - эта тема давно стала основной для мемов, шуток и анекдотов, то что с аналогичными женскими аксессуарами? Смотрим статистику продаж таких товаров за месяц - анализируем категорию "Чулки, носки и колготки". Показатели продаж и выручки стабильны, но ближе к концу месяца начинают тянуться вниз. Девушки, вполне возможно, могли закупиться носочками на январских распродажах, а молодые люди просто не считают их хорошим подарком. И даже при этом, за последнюю неделю февраля, женские аксессуары продавались в среднем на 300 000 рублей в день.

данные сервиса SellerFox в категории "Женская одежда-Чулки, носки, колготки" маркетплейса OZONданные сервиса SellerFox в категории "Женская одежда-Чулки, носки, колготки" маркетплейса OZON

Смотрим на самые популярные товары в категории. Делаем вывод: носочки у девушек тоже рвутся. Комплекты женских носков покупают чаще всего, хотя такие товары приносят селлерам меньше, чем штучные колготки или аналогичные мужские наборы. Самая прибыльная модель женских носков подарила продавцам за месяц 186784рублей.

Кстати, OZON в этой категории снова не победил. В анализируемой нише больше всего выручки получил "Декатлон" - 1 947 876 рублей. Его ближайший конкурент заработал чуть больше 1,5 млн. рублей, а сам маркетплейс всего 882 551 рубль. Ну что, поможем OZON и подарим носки вторым половинкам?

данные сервиса SellerFox в категории "Чулки, носки, колготки" OZON, срез по продавцам, период с 12.01-11.02.21данные сервиса SellerFox в категории "Чулки, носки, колготки" OZON, срез по продавцам, период с 12.01-11.02.21

Растаптываем выручку

Идем дальше: 5% опрошенных OZON заявили, что не хотели бы получить в подарок на День всех влюбленных тапочки. Были прецеденты? В нашей практике таких подарков не встречалось, потому проверить спрос на этот аксессуар интересно. Другое дело, что тапочки могут покупать не только для дома, но и, например, для поездки в больницу. Так что давайте просто проверим - есть ли деньги в этой категории товаров. Кстати, пока вы читаете эти строки, мы тоже не знаем ответа. Данные проанализируем сразу после того как поставим в следующем предложении точку. Сгораем от нетерпения.

данные сервиса SellerFox в категории "Мужская одежда-Домашняя обувь" маркетплейса OZON, период с 12.01 - 11.02данные сервиса SellerFox в категории "Мужская одежда-Домашняя обувь" маркетплейса OZON, период с 12.01 - 11.02

Анализировать будем сразу две категории, потому что "Тапочки" можно встретить как среди мужской, так и среди женской одежды. Смотрим на выборку товаров "Домашняя обувь", вложенную в большую категорию "Мужская одежда" - здесь продаются тапочки. Видно, что спрос на такие аксессуары не велик. Средняя дневная выручка продавцов за последний месяц составила меньше 100 тысяч рублей, а лидер продаж заработал с 12.01 по 11.02 всего 63 552 рубля. Взгляните на топовый товар - он не похож ни на подарок, ни на предмет больничного гардероба.

самый популярный товар на OZON в категории "Мужская одежда-Домашняя обувь", период с 12.01-11.02.21самый популярный товар на OZON в категории "Мужская одежда-Домашняя обувь", период с 12.01-11.02.21

Забавно, но маркетплейс вообще не борется за выручку в категории "Домашняя обувь" - на итоговом графике его едва можно найти. Давай посмотрим на аналогичную статистику продаж "Домашней обуви", входящей в категорию "Женская одежда". Среди популярных продавцов снова нет OZON, зато популярный товар в этой подкатегории заработал за месяц чуть больше - 87 210 рублей. И это при том, что продан он был в меньшем количестве, чем самые популярные мужские тапочки. В целом, женская версия этого уютного атрибута стабильно приносит продавцам больше денег. А еще она выглядит в разы эффектнее. Дарить вроде можно, но мы ажиотажного спроса не видим.

данные сервиса SellerFox в категории "Женская одежда-Домашняя обувь" маркетплейса OZON, период с 12.01 - 11.02данные сервиса SellerFox в категории "Женская одежда-Домашняя обувь" маркетплейса OZON, период с 12.01 - 11.02

Мягкий спрос

Перейдем к анализу продаж мягких игрушек. В результатах опроса OZON указано, что 18% респондентов будут недовольны, если получат такой подарок. Смотрим на графики и узнаем насколько велика вероятность получить на 14 февраля плюшевого мишку.

данные сервиса SellerFox в категории "Мягкие игрушки" маркетплейса OZON, период с 12.01 - 11.02данные сервиса SellerFox в категории "Мягкие игрушки" маркетплейса OZON, период с 12.01 - 11.02

"Мягкие игрушки" продаются в категории "Детские товары". Они стоят особняком от игрушек для мальчиков и девочек, да и вообще могли бы занять свое место среди взрослых товаров. Спрос на мягкие игрушки потрясающий и, очевидно, что не все эти товары предназначены для детей. Посмотрите, средние значения дневной выручки продавцов за последний месяц колеблются между 4 и 5 миллионами рублей. А что с топом продаж? Он совсем не похож на детскую игрушку - много ли вы знаете детей, которые увлечены Тоторо? Именно он принес продавцу за прошедшую неделю почти 5,2 млн. рублей. Да, спрос на него в последние дни подрос, но связанно ли это с днем всех влюбленных? Заметьте, в топе продаж нет никаких плюшевых мишек и сердец.

самый популярный товар на OZON в категории "Мягкие игрушки", период с 13.01-12.02.21, данные SellerFoxсамый популярный товар на OZON в категории "Мягкие игрушки", период с 13.01-12.02.21, данные SellerFox

Напоследок вновь сравним достижения OZON и его продавцов. С 13 января по 12 февраля в категории мягкой игрушки маркетплейс самостоятельно заработал чуть больше 1,2 млн. рублей. Лидер продаж сделал на плюшевых товарах, страшно представить - 68 000 000 рублей. А что если, ради шутки, представить будто OZON выдает за результаты опроса категории товаров в которых ему просто не очень везет?

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

Возможно, мы ошибаемся и дарить два раза в месяц комплекты носков - отличная идея. Выручка растёт. Скорее всего, продавцам пора задавать тренды на подарки самим. Сердечки на открытках, шоколадках и носках - слишком очевидный способ поздравить вторую половину. А вот если найти "ту самую" нишу и заразить новым товаром покупателей, возможно, 14 февраля станет взрывным поводом для роста продаж. Тогда уже в следующем году, опросы OZON покажут, что День всех влюблённых будут отмечать хотя бы 90% россиян.Просто потому, что им станет ясно кому и, главное, что дарить.

Подробнее..

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru