Опубликовано: 21 фев 2019
Данный пример иллюстрирует, как можно анализировать данные веб аналитики с помощью Jupyter notebook и сделать некоторые отчеты автоматическими в данной среде.
Почему Jupyter notebook? Да, конечно, существует целый ряд замечательных инструментов специально предназначенных для аналитики и визуализации данных, такие как, Google Data Studio, Tableau, Power BI и другие, в которых наверное большую часть описанного в данной статье можно было бы реализовать более простыми шагами и где-то нагляднее. Что же предлагает данный метод, чего нет в перечисленных инструментах и что может стать дополнительной ценностью для аналитика данных?
Часть из перечисленных инструментов платные, что уже может повлиять на выбор в каких-то случаях. Но наверно основное, что предлагает данный метод — это больше возможностей для интерактивного анализа. Под интерактивным анализом я подразумеваю первую стадию исследования данных, когда возможно вы еще не знаете, как в точности будет сформирован ваш конечный отчет, и как на его вид повлияют промежуточные результаты. Или же возможно, вы хотите посмотреть на данные с разных сторон, получив их, к примеру, через разные алгоритмы или разные API прежде чем собирать результирующий отчет.
В этом примере мы будем анализировать данные Google Analytics из таблицы BigQuery, созданной через стриминг хитов в BigQuery с проектом в Google Cloud Platform (GCP), но подход естественно может быть применен к анализу любых других источников данных.
Чтобы не описывать базовые элементы, фигурирующие в этой статье, вот несколько ссылок для ознакомления:
Подразумевается, что у читателя есть некоторые представления о Python и Pandas. В данном примере также будут упоминаться некоторые элементы Google Cloud Platform (GCP). В качестве облачной платформы для работы с Jupyter notebook выбрана Microsoft Azure Notebooks.
Чтобы иметь возможность обращаться к нашей таблице в BigQuery из Jupyter notebook, нам необходимо в нашем проекте в GCP создать так называемый ключ сервисного аккаунта и скачать соответствующий json файл для процесса авторизации. Это можно сделать, следуя инструкциям на странице введение в авторизацию в GCP.
Далее нам нужно зарегистрироваться в облачной платформе Microsoft Azure Notebooks, создать там проект и наш первый Python notebook:
Для наших целей нужно создать Python 3.6 notebook без публичного доступа, поскольку следующим шагом следует поместить json файл нашего сервисного ключа GCP в папку проекта ноутбука, и естественно к нему не должно быть доступа из вне. Параметры проета можно задавать и менять в разделе Project Settings.
Для решения задачи нам нужно будет установить несколько дополнительных пакетов. В первую очередь давайте установим библиотеки BigQuery:
%%capture
!pip install --upgrade google-cloud-bigquery
Проверить установился ли пакет можно с помощью следующей команды. Если установка успешна команда выведет данные о пакете google-cloud-bigquery:
!pip show google-cloud-bigquery
Теперь можно импортировать данную библиотеку в ноутбук и авторизоваться для работы с API BigQuery с помощью сервисного ключа:
from google.cloud import bigquery
import os
os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'yourkey.json'
client = bigquery.Client()
%load_ext google.cloud.bigquery
После авторизации в GCP & BigQuery мы можем перейти к эксплораторному интерактивному анализу, продвигаясь при необходимости от простых запросов к более сложным, стараясь найти решение или оптимизировать алгоритм. Для иллюстрации, давайте, например, простым запросом узнаем количество посетителей за прошедшие 7 дней:
%%bigquery --project yourproject
SELECT
COUNT(DISTINCT clientId) users
FROM
`yourproject.gastreaming.hits`
WHERE
_PARTITIONDATE BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY) AND DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)
Как вы могли заметить, мы используем magic function %%bigquery --project yourproject
, которая позволяет нам писать запросы к API BigQuery с минимумом кода, т.е. практически так же, как мы бы это делали в интерфейсе BigQuery и сразу помещать ответ в pandas dataframe.
В качестве примера задачи предположим, что мы хотим проанализировать некую маркетинговую воронку у нас на сайте. На следующем шаге усложним немного предыдущий запрос, и получим количество пользователей, посетивших раздел, с которого начинается предполагаемая воронка:
%%bigquery --project yourproject
SELECT
COUNT(DISTINCT clientId) users
FROM
`yourproject.gastreaming.hits`
WHERE
_PARTITIONDATE BETWEEN DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY) AND DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY)
AND REGEXP_CONTAINS(page.path,'popup')
По аналогии мы можем и дальше усложнять наши запросы, объединять их по каким-то условиям, чтобы создать некий результирующий запрос, который поможет нам получить достаточно комплексные данные о нашей воронке. Предположим мы создали такой SQL запрос. Если он получился достаточно громоздким, мы можем записать его в отдельный файл, сохранив его, к примеру, в той же директории, где находится и наш ноутбук.
Открываем файл с нашим SQL запросом и сохраняем его содержимое в переменную:
f=open("funnel.sql", "r")
sql = f.read()
Отправляем SQL запрос в BigQuery и записываем ответ в pandas datafame:
df = client.query(sql).to_dataframe()
df.head()
Данный запрос был сконструирован в ходе интерактивного анализа, в результате он дает список пользовательских clientId на разных этапах прохождения воронки. Этапы отражены в таблице слева направо.
Чтобы найти количество пользователей на каждом этапе воронки в течение каждого дня на выбранном интервале найдем количество пользовательских clientId с помощью функций агрегирования:
fdaily=df.groupby('date').agg({'base_clientId' : 'count','login_clientId' : 'count',
'reg_clientId' : 'count','checkout_clientId' : 'count'}).reset_index()
fdaily.head()
Заново отсортируем и переименуем колонки таблицы, для более наглядного представления в отчете:
fdaily = fdaily[['date','base_clientId','login_clientId','reg_clientId','checkout_clientId']]
fdaily = fdaily.rename(columns={"reg_clientId": "users on registration page", "checkout_clientId": "users on checkout page",
"base_clientId": "users visited funnel", "login_clientId": "users on login page"})
fdaily.head()
fdaily.tail()
Трансформируем таблицу, объединив четыре колонки шагов воронки в одну колонку:
fmelt = fdaily.melt('date', var_name='Funnel', value_name='Users')
fmelt.head()
Перейдем к построению графиков, для этого импортируем пакеты matplotlib и seaborn и построим с их помощью график прохождения нашей воронки по дням на выбранном временном интервале.
%%capture
import matplotlib.pyplot as plt
import seaborn as sns
from IPython.display import set_matplotlib_formats
set_matplotlib_formats('svg')
sns.set_style("darkgrid")
sns.set_context(rc={"lines.linewidth":0.8})
ax = sns.catplot(x="date", y="Users", hue='Funnel', height=4, aspect=2, kind='point', data=fmelt, legend_out = True)
ax.set_xticklabels(rotation=30)
ax.set(xlabel='Date', ylabel='Users')
plt.show()
Теперь нам хотелось бы посмотреть на воронку не по дням, а на всем выбранном интервале. Мы легко можем убрать колонку даты и просуммировать данные по всему интервалу:
fusers = fdaily[fdaily.filter(like='users').columns.tolist()]
ftotals = dict(zip(fusers.columns.tolist(),fusers.sum().tolist()))
ftotals
Построим график воронки с помощью обычной столбчатой диаграммы:
plt.figure(figsize=(7,3))
fig = plt.bar(range(len(ftotals)), list(ftotals.values()), align='center',color=sns.color_palette("Blues",7))
plt.xticks(range(len(ftotals)), list(ftotals.values()))
b2 = str(round(ftotals['users on login page']/ftotals['users visited funnel']*100,2))+'%'
b3 = str(round(ftotals['users on registration page']/ftotals['users visited funnel']*100,2))+'%'
b4 = str(round(ftotals['users on checkout page']/ftotals['users visited funnel']*100,2))+'%'
plt.xticks(range(len(ftotals)), ['100%',b2,b3,b4])
plt.legend(fig, list(ftotals.keys()), loc = "upper right", title = "Funnel")
for rect in fig:
height = rect.get_height()
plt.text(rect.get_x() + rect.get_width()/2.0, height/2, '%d' % int(height), ha='center', va='bottom')
plt.show()
Получив нашу воронку и оформив комментарии, мы можем теперь подумать о том, как автоматизировать часть или весь процесс предоставления отчетности.
Для начала давайте экспортируем наш ноутбук в html файл
%%capture
!pip install jupyter_contrib_nbextensions
!jupyter nbconvert funnel1.ipynb --to html --log-level WARN
Теперь отправим его на наш сервер через ftp-соединение в раздел отчетов:
import ftplib
ftp = ftplib.FTP('ftp.byethost10.com','b10_22228720','website1lytics')
ftp.cwd('/lytics.website/htdocs/reports')
with open('funnel1.html', 'rb') as ftpup:
ftp.storbinary('STOR ' + 'funnel1.html', ftpup)
ftp.close()
Таким образом, например, для еженедельной отчетности достаточно сообщить клиенту ссылку на отчет и автоматизировать подготовку и отправку отчета либо частично, либо полностью в зависимости от технических возможностей.
Но все же основой особенностью данного подхода является возможность исследовательского интерактивного анализа данных, например, с использованием различных API, в одном удобном интерфейсе с возможностью комментировать свой код и действия, если это будет необходимо в рамках совместной работы с коллегами или, как часть документации к выполненному заданию.