В современном мире данных и аналитики ключом к успеху любого онлайн-бизнеса является глубокое понимание поведения пользователей и эффективности продукта. В этой статье я поделюсь своим опытом использования Python для расчета и анализа продуктовых метрик, которые помогают принимать обоснованные решения и оптимизировать бизнес-процессы.
Мы погрузимся в мир веб-аналитики, рассмотрим ключевые продуктовые метрики и научимся их вычислять с помощью Python. Я покажу, как использовать популярные библиотеки для обработки данных, визуализации результатов и даже применения методов машинного обучения для прогнозирования поведения пользователей. Независимо от того, являетесь ли вы продакт-менеджером, маркетологом или дата саентистом, эта статья поможет вам извлечь максимум пользы из ваших данных веб-аналитики.
Подготовка данных для анализа
Прежде чем мы приступим к расчету метрик, необходимо правильно подготовить наши данные. В этом разделе мы рассмотрим процесс загрузки, очистки и предварительной обработки данных веб-аналитики с использованием Python.
Загрузка и первичный осмотр данных
Начнем с загрузки нашего датасета. Для этого мы будем использовать библиотеку pandas, которая предоставляет удобные инструменты для работы с табличными данными.
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
# Загрузка данных
df = pd.read_csv('web_analytics_data.csv')
# Просмотр первых нескольких строк
print(df.head())
# Общая информация о датасете
print(df.info())
Этот код загружает наш датасет и выводит первые несколько строк, а также общую информацию о структуре данных. Для примеров в этой статье я загрузил датасет с типовой структурой от счетчика Яндекс Метрика, выгруженного с помощью Logs API, обогащенного дополнительными столбцами и экспортированного в формат csv.
Очистка и предобработка данных
После загрузки данных необходимо провести их очистку и предобработку. Данный этап включает в себя обработку пропущенных значений, преобразование типов данных и создание новых признаков, которые могут быть полезны для нашего анализа.
# Преобразование строковых дат в datetime
df['HitDateTime'] = pd.to_datetime(df['HitDateTime'])
df['VisitDateTime'] = pd.to_datetime(df['VisitDateTime'])
# Обработка пропущенных значений
df['Referer'].fillna('Direct', inplace=True)
df['UTMSource'].fillna('Unknown', inplace=True)
df['UTMMedium'].fillna('Unknown', inplace=True)
df['UTMCampaign'].fillna('Unknown', inplace=True)
df['UTMTerm'].fillna('Unknown', inplace=True)
# Создание новых признаков
df['DayOfWeek'] = df['HitDateTime'].dt.dayofweek
df['Hour'] = df['HitDateTime'].dt.hour
# Преобразование массивов в строки для удобства работы
df['PageGoals'] = df['PageGoals'].apply(lambda x: str(x))
df['PageGoalsTime'] = df['PageGoalsTime'].apply(lambda x: str(x))
df['GoalsID'] = df['GoalsID'].apply(lambda x: str(x))
df['GoalsDateTime'] = df['GoalsDateTime'].apply(lambda x: str(x))
print(df.dtypes)
В этом коде мы выполняем несколько важных шагов:
- Преобразуем строковые даты в формат datetime для удобства дальнейших расчетов;
- Заполняем пропущенные значения в столбцах, связанных с источниками трафика и UTM-метками;
- Создаем новые признаки, такие как день недели и час, которые могут быть полезны для анализа временных паттернов;
- Преобразуем массивы в строки для упрощения работы с ними (в реальном сценарии мы бы использовали более сложную логику для работы с этими данными).
Агрегация данных на уровне сессий
Для многих метрик нам потребуются данные, агрегированные на уровне сессий пользователей. Давайте создадим такой агрегированный датафрейм:
session_data = df.groupby('VisitID').agg({
'ClientID': 'first',
'VisitDateTime': 'first',
'VisitDuration': 'max',
'Pageviews': 'max',
'isNewUser': 'max',
'Source': 'first',
'UTMSource': 'first',
'UTMMedium': 'first',
'UTMCampaign': 'first'
})
print(session_data.head())
Этот код группирует наши данные по ID сессии (VisitID) и агрегирует различные метрики. Например, мы берем первое значение ClientID для каждой сессии, максимальное значение VisitDuration и Pageviews, и т.д.
Теперь, когда наши данные подготовлены, мы можем приступить к расчету и анализу различных продуктовых метрик. В следующих разделах мы рассмотрим как базовые, так и продвинутые метрики, которые помогут нам глубже понять поведение пользователей и эффективность нашего онлайн-продукта: веб-сайта или приложения.
Базовые метрики веб-аналитики
Начнем наш анализ с расчета базовых метрик веб-аналитики. Эти метрики являются фундаментом для понимания поведения пользователей на сайте и эффективности различных каналов привлечения трафика.
Посещаемость и просмотры страниц
Одними из самых базовых, но от этого не менее важных метрик являются количество посещений (сессий) и просмотров страниц. Давайте рассчитаем эти метрики и визуализируем их динамику во времени.
# Расчет ежедневных посещений и просмотров
daily_metrics = session_data.resample('D', on='VisitDateTime').agg({
'VisitID': 'count',
'Pageviews': 'sum'
}).rename(columns={'VisitID': 'Visits'})
# Визуализация
plt.figure(figsize=(12, 6))
plt.plot(daily_metrics.index, daily_metrics['Visits'], label='Visits')
plt.plot(daily_metrics.index, daily_metrics['Pageviews'], label='Pageviews')
plt.title('Daily Visits and Pageviews')
plt.xlabel('Date')
plt.ylabel('Count')
plt.legend()
plt.show()
print(daily_metrics.describe())
Этот код рассчитывает ежедневное количество посещений и просмотров страниц, а затем визуализирует эти метрики на графике. Мы также выводим описательную статистику для этих метрик, что позволяет быстро оценить средние значения, медиану, минимум и максимум.
Показатель отказов (Bounce Rate)
Ниже я покажу как считаю показатель отказов от Google – это процент сессий, в которых пользователь просмотрел только 1 страницу и не совершил никаких действий. В отличие от Яндекса, сюда не входят сессии с длительностью до 15 секунд, а считаются именно просмотры страниц. Высокий показатель отказов может свидетельствовать о проблемах с контентом или пользовательским опытом.
def calculate_bounce_rate(group):
return (group['Pageviews'] == 1).mean()
bounce_rate = session_data.groupby('UTMSource').apply(calculate_bounce_rate)
plt.figure(figsize=(10, 6))
bounce_rate.plot(kind='bar')
plt.title('Bounce Rate by UTM Source')
plt.xlabel('UTM Source')
plt.ylabel('Bounce Rate')
plt.xticks(rotation=45)
plt.show()
print(bounce_rate)
Здесь мы рассчитываем показатель отказов для каждого источника трафика (UTMSource) и визуализируем результаты в виде столбчатой диаграммы. Это позволяет нам сравнить эффективность различных каналов привлечения трафика с точки зрения удержания пользователей на сайте.
Средняя продолжительность сессии
Средняя продолжительность сессии – еще одна важная метрика, которая может указывать на уровень вовлеченности пользователей.
avg_session_duration = session_data.groupby('UTMSource')['VisitDuration'].mean()
plt.figure(figsize=(10, 6))
avg_session_duration.plot(kind='bar')
plt.title('Average Session Duration by UTM Source')
plt.xlabel('UTM Source')
plt.ylabel('Average Duration (seconds)')
plt.xticks(rotation=45)
plt.show()
print(avg_session_duration)
Этот код рассчитывает среднюю продолжительность сессии для каждого источника трафика и визуализирует результаты. Это помогает понять, какие источники трафика приводят наиболее заинтересованных пользователей.
Коэффициент конверсии
Коэффициент конверсии – это отношение количества пользователей, достигших определенной цели (например, совершивших покупку), к общему количеству посетителей. Давайте рассчитаем общий коэффициент конверсии и коэффициент конверсии по источникам трафика.
def has_completed_goal(goals):
return len(eval(goals)) > 0 if goals != '[]' else False
session_data['HasCompletedGoal'] = session_data.index.map(df.set_index('VisitID')['GoalsID'].apply(has_completed_goal))
overall_conversion_rate = session_data['HasCompletedGoal'].mean()
conversion_rate_by_source = session_data.groupby('UTMSource')['HasCompletedGoal'].mean()
plt.figure(figsize=(10, 6))
conversion_rate_by_source.plot(kind='bar')
plt.title('Conversion Rate by UTM Source')
plt.xlabel('UTM Source')
plt.ylabel('Conversion Rate')
plt.xticks(rotation=45)
plt.show()
print(f"Overall Conversion Rate: {overall_conversion_rate:.2%}")
print("\nConversion Rate by UTM Source:")
print(conversion_rate_by_source)
В этом коде мы сначала определяем, достиг ли пользователь какой-либо цели во время сессии. Затем мы рассчитываем общий коэффициент конверсии и коэффициент конверсии для каждого источника трафика. Визуализация помогает быстро определить наиболее эффективные источники с точки зрения конверсии.
Эти базовые метрики являются критически важными для понимания поведения пользователей на вашем сайте. Это база, это фундамент. Тем не менее, для более глубокого анализа и принятия стратегических решений нам понадобятся более продвинутые метрики и техники анализа, которые мы рассмотрим в следующих разделах.
Продвинутые метрики и анализ пользовательского пути
После рассмотрения базовых метрик давайте перейдем к более сложным показателям и методам анализа, которые помогут нам глубже понять поведение пользователей и эффективность нашего продукта.
Начнем с того как можно посчитать ключевые для бизнеса продуктовые метрики из данных веб-аналитики.
Количество лидов:
leads = df[df['HasCompletedGoal'] == True]['ClientID'].nunique()
print(f"Количество лидов: {leads}")
Процент конверсии посетителей сайта в лиды (CR1):
total_visitors = df['ClientID'].nunique()
lead_conversion_rate = leads / total_visitors * 100
print(f"Процент конверсии в лид: {lead_conversion_rate:.2f}%")
Цена за лид в неделю и месяц:
# Предположим, у нас есть столбец 'Cost' с затратами на рекламу
df['Week'] = df['VisitDateTime'].dt.to_period('W')
df['Month'] = df['VisitDateTime'].dt.to_period('M')
weekly_cost_per_lead = df.groupby('Week').apply(lambda x: x['Cost'].sum() / x[x['HasCompletedGoal'] == True]['ClientID'].nunique())
monthly_cost_per_lead = df.groupby('Month').apply(lambda x: x['Cost'].sum() / x[x['HasCompletedGoal'] == True]['ClientID'].nunique())
print("Цена за лид по неделям:")
print(weekly_cost_per_lead)
print("\nЦена за лид по месяцам:")
print(monthly_cost_per_lead)
Цена за лид накопленным итогом от указанной даты:
start_date = pd.Timestamp('2023-01-01')
cumulative_cost_per_lead = df[df['VisitDateTime'] >= start_date].groupby(df['VisitDateTime'].dt.date).apply(
lambda x: x['Cost'].sum() / x[x['HasCompletedGoal'] == True]['ClientID'].nunique()
).cumsum()
print("Цена за лид накопленным итогом:")
print(cumulative_cost_per_lead)
Процент вернувшихся посетителей:
total_visitors = df['ClientID'].nunique()
returning_visitors = df.groupby('ClientID').filter(lambda x: len(x) > 1)['ClientID'].nunique()
returning_visitors_rate = returning_visitors / total_visitors * 100
print(f"Процент вернувшихся посетителей: {returning_visitors_rate:.2f}%")
Процент вовлеченных посетителей (посмотревших 3 и более страницы):
engaged_visitors = df.groupby('ClientID').filter(lambda x: x['Pageviews'].sum() >= 3)['ClientID'].nunique()
engaged_rate = engaged_visitors / total_visitors * 100
print(f"Процент вовлеченных посетителей: {engaged_rate:.2f}%")
Процент конверсии из лидов в продажи (CR2):
# Предположим, у нас есть столбец 'Purchase' для обозначения продаж
sales = df[(df['HasCompletedGoal'] == True) & (df['Purchase'] == True)]['ClientID'].nunique()
lead_to_sale_rate = sales / leads * 100
print(f"Процент конверсии из лидов в продажи: {lead_to_sale_rate:.2f}%")
Доля рекламных расходов (ДРР):
total_revenue = df['Revenue'].sum()
total_ad_spend = df['Cost'].sum()
ad_spend_share = total_ad_spend / total_revenue * 100
print(f"Доля рекламных расходов: {ad_spend_share:.2f}%")
Возврат трат на рекламу (ROAS):
roas = total_revenue / total_ad_spend
print(f"Возврат трат на рекламу (ROAS): {roas:.2f}")
Клиентский отток (Churn Rate):
# Предположим, мы считаем клиента ушедшим, если он не посещал сайт более 30 дней
churn_threshold = pd.Timedelta(days=30)
last_visit_date = df.groupby('ClientID')['VisitDateTime'].max()
churned_customers = (pd.Timestamp.now() - last_visit_date > churn_threshold).sum()
total_customers = df['ClientID'].nunique()
churn_rate = churned_customers / total_customers * 100
print(f"Клиентский отток (Churn Rate): {churn_rate:.2f}%")
Возврат маркетинговых инвестиций (ROMI):
romi = (total_revenue - total_ad_spend) / total_ad_spend * 100
print(f"Возврат маркетинговых инвестиций (ROMI): {romi:.2f}%")
Долгосрочная ценность клиента (LTV):
avg_purchase_value = df[df['Purchase'] == True]['Revenue'].mean()
avg_purchase_frequency = df[df['Purchase'] == True].groupby('ClientID')['Purchase'].count().mean()
customer_lifespan = 12 # предположим, средний срок жизни клиента 12 месяцев
ltv = avg_purchase_value * avg_purchase_frequency * customer_lifespan
print(f"Долгосрочная ценность клиента (LTV): {ltv:.2f}")
Эти метрики предоставляют всесторонний взгляд на эффективность сайта и маркетинговых усилий. Они помогают оценить привлечение пользователей, их вовлеченность, конверсию и общую рентабельность онлайн-бизнеса.
Когортный анализ
Когортный анализ позволяет нам отслеживать поведение группы пользователей с течением времени. Это особенно полезно для понимания удержания пользователей и долгосрочной ценности клиента.
import datetime
def get_cohort(df):
df['CohortDate'] = df['VisitDateTime'].dt.to_period('M')
df['CohortIndex'] = (df['VisitDateTime'].dt.to_period('M') -
df.groupby('ClientID')['VisitDateTime'].transform('min').dt.to_period('M')).apply(lambda x: x.n)
return df
cohort_data = get_cohort(session_data.reset_index())
cohort_sizes = cohort_data.groupby('CohortDate')['ClientID'].nunique()
retention_matrix = cohort_data.groupby(['CohortDate', 'CohortIndex'])['ClientID'].nunique().unstack()
retention_rates = retention_matrix.divide(cohort_sizes, axis=0)
plt.figure(figsize=(12, 8))
sns.heatmap(retention_rates, annot=True, fmt='.0%', cmap='YlGnBu')
plt.title('User Retention by Cohort')
plt.xlabel('Months Since First Visit')
plt.ylabel('Cohort')
plt.show()
print(retention_rates)
В предыдущем коде мы создали матрицу удержания пользователей, которая показывает, как различные когорты пользователей (сгруппированные по месяцу их первого посещения) сохраняют активность с течением времени. Эта визуализация позволяет нам быстро определить, улучшается ли удержание пользователей со временем и какие когорты показывают наилучшие результаты.
Анализ воронки конверсии
Анализ воронки конверсии помогает понять, на каких этапах пользовательского пути мы теряем потенциальных клиентов. Давайте создадим и проанализируем простую воронку конверсии.
def get_funnel_stage(row):
if row['Pageviews'] > 0:
if 'product_page' in row['URL']:
if 'add_to_cart' in row['URL']:
if 'checkout' in row['URL']:
if row['HasCompletedGoal']:
return 'Purchase'
return 'Checkout'
return 'Add to Cart'
return 'Product View'
return 'Homepage'
return 'No View'
df['FunnelStage'] = df.apply(get_funnel_stage, axis=1)
funnel_stages = ['Homepage', 'Product View', 'Add to Cart', 'Checkout', 'Purchase']
funnel_data = df['FunnelStage'].value_counts().reindex(funnel_stages)
plt.figure(figsize=(10, 6))
plt.bar(funnel_data.index, funnel_data.values)
plt.title('Conversion Funnel')
plt.xlabel('Funnel Stage')
plt.ylabel('Number of Users')
plt.xticks(rotation=45)
plt.show()
for i in range(len(funnel_stages) - 1):
conversion_rate = funnel_data[funnel_stages[i+1]] / funnel_data[funnel_stages[i]]
print(f"Conversion rate from {funnel_stages[i]} to {funnel_stages[i+1]}: {conversion_rate:.2%}")
Этот код создает простую воронку конверсии, начиная с просмотра домашней страницы и заканчивая покупкой. Мы визуализируем воронку и рассчитываем коэффициенты конверсии между каждым этапом. Это помогает выявить этапы, на которых мы теряем наибольшее количество пользователей, и сосредоточить усилия по оптимизации на этих областях.
Анализ пользовательских сегментов
Сегментация пользователей позволяет нам выявить различные группы пользователей с похожим поведением и адаптировать наши стратегии для каждой группы.
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
# Подготовка данных для кластеризации
cluster_data = session_data[['Pageviews', 'VisitDuration']].copy()
cluster_data['ConversionValue'] = session_data['HasCompletedGoal'].astype(int)
# Нормализация данных
scaler = StandardScaler()
cluster_data_scaled = scaler.fit_transform(cluster_data)
# Применение KMeans
kmeans = KMeans(n_clusters=3, random_state=42)
cluster_data['Cluster'] = kmeans.fit_predict(cluster_data_scaled)
# Визуализация результатов
plt.figure(figsize=(12, 8))
scatter = plt.scatter(cluster_data['Pageviews'], cluster_data['VisitDuration'],
c=cluster_data['Cluster'], cmap='viridis', alpha=0.5)
plt.colorbar(scatter)
plt.title('User Segments')
plt.xlabel('Pageviews')
plt.ylabel('Visit Duration (seconds)')
plt.show()
# Анализ характеристик кластеров
print(cluster_data.groupby('Cluster').mean())
В этом примере мы использовали алгоритм KMeans для сегментации пользователей на основе количества просмотров страниц, продолжительности посещения и наличия конверсии. Визуализация помогает нам увидеть, как распределены эти сегменты, а анализ средних значений для каждого кластера дает представление о характеристиках каждого сегмента.
Анализ путей пользователей
Понимание типичных путей пользователей через наш сайт может дать ценные инсайты для оптимизации пользовательского опыта.
from collections import defaultdict
def get_user_paths(group):
return ' > '.join(group['URL'])
user_paths = df.groupby('VisitID').apply(get_user_paths)
path_counts = user_paths.value_counts()
print("Top 10 most common user paths:")
print(path_counts.head(10))
# Визуализация переходов между страницами
page_transitions = defaultdict(lambda: defaultdict(int))
for path in user_paths:
pages = path.split(' > ')
for i in range(len(pages) - 1):
page_transitions[pages[i]][pages[i+1]] += 1
# Преобразование в DataFrame для удобства визуализации
transitions_df = pd.DataFrame(page_transitions).fillna(0)
plt.figure(figsize=(12, 10))
sns.heatmap(transitions_df, annot=True, fmt='g', cmap='YlOrRd')
plt.title('Page Transitions Heatmap')
plt.xlabel('To Page')
plt.ylabel('From Page')
plt.show()
Этот код анализирует и визуализирует типичные пути пользователей через сайт. Мы выводим 10 наиболее распространенных путей и создаем тепловую карту переходов между страницами. Это помогает выявить наиболее популярные маршруты и потенциальные проблемные места в навигации сайта.
Анализ времени до конверсии
Понимание того, сколько времени обычно требуется пользователю для совершения конверсии, может помочь в оптимизации маркетинговых кампаний и пользовательского опыта.
def time_to_conversion(group):
if group['HasCompletedGoal'].any():
first_visit = group['VisitDateTime'].min()
conversion_time = group[group['HasCompletedGoal']]['VisitDateTime'].min()
return (conversion_time - first_visit).total_seconds() / 3600 # в часах
return None
time_to_conversion = session_data.groupby('ClientID').apply(time_to_conversion).dropna()
plt.figure(figsize=(10, 6))
time_to_conversion.hist(bins=50)
plt.title('Time to Conversion Distribution')
plt.xlabel('Time (hours)')
plt.ylabel('Frequency')
plt.show()
print(f"Median time to conversion: {time_to_conversion.median():.2f} hours")
print(f"Mean time to conversion: {time_to_conversion.mean():.2f} hours")
Этот код рассчитывает время от первого посещения до конверсии для каждого пользователя, а затем визуализирует распределение этого времени. Мы также выводим среднее и медианное время до конверсии, что может быть полезно для планирования ремаркетинговых кампаний и оценки эффективности различных каналов привлечения.
Эти продвинутые метрики и методы анализа предоставляют глубокое понимание поведения пользователей и эффективности нашего продукта. Они позволяют выявить области для улучшения, оптимизировать пользовательский опыт и, в конечном итоге, увеличить конверсию и удержание пользователей.
Прогнозирование и машинное обучение в веб-аналитике
Теперь, когда мы глубоко проанализировали наши данные, давайте рассмотрим, как мы можем использовать методы машинного обучения для прогнозирования поведения пользователей и оптимизации нашего продукта.
Прогнозирование вероятности конверсии
Одной из наиболее полезных задач машинного обучения в веб-аналитике является прогнозирование вероятности конверсии для каждого пользователя. Это позволяет нам сосредоточить наши маркетинговые усилия на наиболее перспективных лидах.
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score, classification_report
# Подготовка данных
X = session_data[['Pageviews', 'VisitDuration', 'isNewUser']]
y = session_data['HasCompletedGoal']
# Разделение на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Обучение модели
rf_model = RandomForestClassifier(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
# Оценка модели
y_pred = rf_model.predict(X_test)
y_pred_proba = rf_model.predict_proba(X_test)[:, 1]
print("ROC AUC Score:", roc_auc_score(y_test, y_pred_proba))
print("\nClassification Report:")
print(classification_report(y_test, y_pred))
# Важность признаков
feature_importance = pd.DataFrame({'feature': X.columns, 'importance': rf_model.feature_importances_})
feature_importance = feature_importance.sort_values('importance', ascending=False)
plt.figure(figsize=(10, 6))
plt.bar(feature_importance['feature'], feature_importance['importance'])
plt.title('Feature Importance for Conversion Prediction')
plt.xlabel('Features')
plt.ylabel('Importance')
plt.xticks(rotation=45)
plt.show()
В этом примере мы обучаем модель случайного леса для прогнозирования вероятности конверсии на основе нескольких простых признаков. Мы оцениваем модель с помощью ROC AUC и выводим отчет о классификации. Кроме того, мы визуализируем важность признаков, что помогает понять, какие факторы наиболее сильно влияют на вероятность конверсии.
Прогнозирование оттока пользователей
Другой важной задачей является прогнозирование оттока пользователей. Это помогает нам выявить пользователей, которые могут перестать пользоваться нашим продуктом, и принять меры для их удержания.
from sklearn.preprocessing import LabelEncoder
# Подготовка данных
churn_data = session_data.groupby('ClientID').agg({
'VisitDateTime': lambda x: (pd.Timestamp.now() - x.max()).days,
'Pageviews': 'sum',
'VisitDuration': 'mean',
'HasCompletedGoal': 'sum',
'UTMSource': 'first',
'isNewUser': 'first'
}).reset_index()
# Определение оттока (например, если пользователь не посещал сайт более 30 дней)
churn_data['Churned'] = churn_data['VisitDateTime'] > 30
# Кодирование категориальных переменных
le = LabelEncoder()
churn_data['UTMSource'] = le.fit_transform(churn_data['UTMSource'])
X = churn_data[['Pageviews', 'VisitDuration', 'HasCompletedGoal', 'UTMSource', 'isNewUser']]
y = churn_data['Churned']
# Разделение на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Обучение модели
rf_model = RandomForestClassifier(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
# Оценка модели
y_pred = rf_model.predict(X_test)
y_pred_proba = rf_model.predict_proba(X_test)[:, 1]
print("ROC AUC Score:", roc_auc_score(y_test, y_pred_proba))
print("\nClassification Report:")
print(classification_report(y_test, y_pred))
# Важность признаков
feature_importance = pd.DataFrame({'feature': X.columns, 'importance': rf_model.feature_importances_})
feature_importance = feature_importance.sort_values('importance', ascending=False)
plt.figure(figsize=(10, 6))
plt.bar(feature_importance['feature'], feature_importance['importance'])
plt.title('Feature Importance for Churn Prediction')
plt.xlabel('Features')
plt.ylabel('Importance')
plt.xticks(rotation=45)
plt.show()
Этот код создает модель для прогнозирования оттока пользователей. Мы определяем отток как отсутствие активности пользователя в течение более 30 дней. Модель обучается на различных признаках, включая общее количество просмотров страниц, среднюю продолжительность посещения, количество достигнутых целей и источник трафика.
Кластеризация пользователей для персонализации
Кластеризация пользователей может помочь нам создать персонализированный опыт для различных групп пользователей. Давайте используем алгоритм K-means для сегментации наших пользователей.
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score
# Подготовка данных для кластеризации
cluster_data = churn_data[['Pageviews', 'VisitDuration', 'HasCompletedGoal', 'UTMSource']]
# Нормализация данных
scaler = StandardScaler()
cluster_data_scaled = scaler.fit_transform(cluster_data)
# Определение оптимального количества кластеров
inertias = []
silhouette_scores = []
for k in range(2, 11):
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans.fit(cluster_data_scaled)
inertias.append(kmeans.inertia_)
silhouette_scores.append(silhouette_score(cluster_data_scaled, kmeans.labels_))
# Визуализация метода локтя
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.plot(range(2, 11), inertias, marker='o')
plt.title('Elbow Method')
plt.xlabel('Number of clusters')
plt.ylabel('Inertia')
plt.subplot(1, 2, 2)
plt.plot(range(2, 11), silhouette_scores, marker='o')
plt.title('Silhouette Score')
plt.xlabel('Number of clusters')
plt.ylabel('Silhouette Score')
plt.tight_layout()
plt.show()
# Выбираем оптимальное количество кластеров (например, 4)
optimal_clusters = 4
# Применяем KMeans с оптимальным количеством кластеров
kmeans = KMeans(n_clusters=optimal_clusters, random_state=42)
cluster_labels = kmeans.fit_predict(cluster_data_scaled)
# Добавляем метки кластеров к нашим данным
churn_data['Cluster'] = cluster_labels
# Анализируем характеристики каждого кластера
cluster_analysis = churn_data.groupby('Cluster').agg({
'Pageviews': 'mean',
'VisitDuration': 'mean',
'HasCompletedGoal': 'mean',
'Churned': 'mean'
})
print("Cluster Analysis:")
print(cluster_analysis)
# Визуализация кластеров
plt.figure(figsize=(12, 8))
scatter = plt.scatter(churn_data['Pageviews'], churn_data['VisitDuration'],
c=churn_data['Cluster'], cmap='viridis', alpha=0.5)
plt.colorbar(scatter)
plt.title('User Clusters')
plt.xlabel('Pageviews')
plt.ylabel('Visit Duration (seconds)')
plt.show()
В этом коде мы выполняем следующие шаги:
- Подготавливаем данные для кластеризации, выбирая релевантные признаки;
- Нормализуем данные с помощью StandardScaler;
- Определяем оптимальное количество кластеров, используя метод локтя и силуэтный анализ;
- Применяем алгоритм KMeans с оптимальным количеством кластеров;
- Анализируем характеристики каждого кластера;
- Визуализируем кластеры на графике.
Этот анализ позволяет нам идентифицировать различные сегменты пользователей, которые могут требовать разных подходов к взаимодействию и маркетингу.
Рекомендательная система для персонализации контента
Рекомендательные системы могут значительно улучшить пользовательский опыт, предлагая релевантный контент или продукты. Давайте создадим простую рекомендательную систему на основе коллаборативной фильтрации.
from sklearn.metrics.pairwise import cosine_similarity
# Предположим, у нас есть данные о просмотрах страниц пользователями
user_page_views = df.groupby(['ClientID', 'URL'])['Pageviews'].sum().unstack(fill_value=0)
# Вычисляем косинусное сходство между пользователями
user_similarity = cosine_similarity(user_page_views)
# Функция для получения рекомендаций для пользователя
def get_recommendations(user_id, top_n=5):
user_index = user_page_views.index.get_loc(user_id)
similar_users = user_similarity[user_index].argsort()[::-1][1:top_n+1]
recommendations = user_page_views.iloc[similar_users].mean().sort_values(ascending=False)
# Исключаем страницы, которые пользователь уже посетил
user_pages = set(user_page_views.loc[user_id][user_page_views.loc[user_id] > 0].index)
recommendations = recommendations[~recommendations.index.isin(user_pages)]
return recommendations.head(top_n)
# Пример использования
sample_user = user_page_views.index[0]
recommendations = get_recommendations(sample_user)
print(f"Top 5 recommended pages for user {sample_user}:")
print(recommendations)
# Оценка эффективности рекомендаций
def evaluate_recommendations(test_size=0.2):
from sklearn.model_selection import train_test_split
train, test = train_test_split(user_page_views, test_size=test_size, random_state=42)
hit_rate = 0
for user in test.index:
actual_pages = set(test.loc[user][test.loc[user] > 0].index)
recommended_pages = set(get_recommendations(user, top_n=10).index)
if actual_pages & recommended_pages:
hit_rate += 1
hit_rate /= len(test)
return hit_rate
hit_rate = evaluate_recommendations()
print(f"Hit Rate: {hit_rate:.2f}")
В этом примере мы создаем простую рекомендательную систему, основанную на коллаборативной фильтрации:
- Создаем матрицу пользователь-страница, показывающую, сколько раз каждый пользователь просмотрел каждую страницу;
- Вычисляем косинусное сходство между пользователями на основе их поведения просмотра страниц;
- Создаем функцию get_recommendations, которая находит похожих пользователей и рекомендует страницы на основе их поведения;
- Демонстрируем использование системы рекомендаций для примера пользователя;
- Создаем функцию evaluate_recommendations для оценки эффективности нашей системы рекомендаций, используя метрику hit rate.
Такая рекомендательная система может быть использована для персонализации контента на сайте, улучшения навигации и увеличения вовлеченности пользователей.
Прогнозирование времени до следующего посещения
Прогнозирование времени до следующего посещения может помочь в планировании маркетинговых кампаний и персонализации коммуникаций с пользователями.
from sklearn.ensemble import RandomForestRegressor
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
# Подготовка данных
user_visits = df.groupby('ClientID')['VisitDateTime'].agg(list).reset_index()
user_visits['TimeBetweenVisits'] = user_visits['VisitDateTime'].apply(lambda x: [(x[i+1] - x[i]).total_seconds()/86400 for i in range(len(x)-1)])
user_visits['MeanTimeBetweenVisits'] = user_visits['TimeBetweenVisits'].apply(lambda x: np.mean(x) if len(x) > 0 else np.nan)
user_visits['LastVisit'] = user_visits['VisitDateTime'].apply(lambda x: x[-1])
# Объединяем с другими характеристиками пользователя
user_features = churn_data.merge(user_visits[['ClientID', 'MeanTimeBetweenVisits', 'LastVisit']], on='ClientID')
# Подготовка признаков и целевой переменной
X = user_features[['Pageviews', 'VisitDuration', 'HasCompletedGoal', 'UTMSource', 'MeanTimeBetweenVisits']]
y = (pd.Timestamp.now() - user_features['LastVisit']).dt.total_seconds() / 86400 # дни с последнего визита
# Разделение на обучающую и тестовую выборки
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Обучение модели
rf_model = RandomForestRegressor(n_estimators=100, random_state=42)
rf_model.fit(X_train, y_train)
# Прогнозирование
y_pred = rf_model.predict(X_test)
# Оценка модели
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)
print(f"Mean Squared Error: {mse:.2f}")
print(f"R-squared Score: {r2:.2f}")
# Важность признаков
feature_importance = pd.DataFrame({'feature': X.columns, 'importance': rf_model.feature_importances_})
feature_importance = feature_importance.sort_values('importance', ascending=False)
plt.figure(figsize=(10, 6))
plt.bar(feature_importance['feature'], feature_importance['importance'])
plt.title('Feature Importance for Next Visit Prediction')
plt.xlabel('Features')
plt.ylabel('Importance')
plt.xticks(rotation=45)
plt.show()
В этом примере мы создаем модель для прогнозирования времени до следующего посещения пользователя:
- Подготавливаем данные, вычисляя среднее время между посещениями для каждого пользователя;
- Объединяем эти данные с другими характеристиками пользователя;
- Обучаем модель случайного леса для прогнозирования времени до следующего посещения;
- Оцениваем модель с помощью среднеквадратичной ошибки и R-squared;
- Визуализируем важность признаков для понимания, какие факторы наиболее сильно влияют на время до следующего посещения.
Эта модель может быть использована для определения оптимального времени для отправки напоминаний или маркетинговых сообщений пользователям.
Оптимизация и A/B тестирование
После глубокого анализа и создания предиктивных моделей, следующим логическим шагом является оптимизация нашего продукта на основе полученных инсайтов. Одним из наиболее эффективных методов оптимизации является A/B тестирование.
Подготовка и проведение A/B теста
Допустим, мы хотим протестировать новый дизайн целевой страницы. Вот как мы можем проанализировать результаты A/B теста:
import scipy.stats as stats
# Симулируем данные A/B теста
np.random.seed(42)
control_group = np.random.binomial(1, 0.1, 1000) # 10% конверсия
treatment_group = np.random.binomial(1, 0.12, 1000) # 12% конверсия
# Рассчитываем конверсию для каждой группы
control_conversion = control_group.mean()
treatment_conversion = treatment_group.mean()
# Проводим статистический тест
z_stat, p_value = stats.ttest_ind(control_group, treatment_group)
print(f"Control Group Conversion: {control_conversion:.2%}")
print(f"Treatment Group Conversion: {treatment_conversion:.2%}")
print(f"P-value: {p_value:.4f}")
# Визуализация результатов
plt.figure(figsize=(10, 6))
plt.bar(['Control', 'Treatment'], [control_conversion, treatment_conversion])
plt.title('A/B Test Results')
plt.ylabel('Conversion Rate')
plt.ylim(0, max(control_conversion, treatment_conversion) * 1.2)
for i, v in enumerate([control_conversion, treatment_conversion]):
plt.text(i, v, f'{v:.2%}', ha='center', va='bottom')
plt.show()
# Расчет размера эффекта
effect_size = (treatment_conversion - control_conversion) / control_conversion
print(f"Relative improvement: {effect_size:.2%}")
# Расчет доверительного интервала
ci = stats.t.interval(alpha=0.95, df=len(control_group)+len(treatment_group)-2,
loc=treatment_conversion - control_conversion,
scale=stats.sem(treatment_group - control_group))
print(f"95% Confidence Interval: {ci}")
Этот код симулирует результаты A/B теста и проводит статистический анализ:
- Мы генерируем данные для контрольной и тестовой групп с разными уровнями конверсии;
- Рассчитываем конверсию для каждой группы;
- Проводим t-тест для определения статистической значимости различий;
- Визуализируем результаты;
- Рассчитываем относительное улучшение и доверительный интервал.
Этот анализ помогает нам определить, действительно ли новый дизайн привел к статистически значимому улучшению конверсии.
Многофакторное тестирование
В реальных сценариях мы часто хотим протестировать несколько изменений одновременно. Давайте рассмотрим пример многофакторного тестирования:
import statsmodels.api as sm
from statsmodels.formula.api import ols
# Симулируем данные многофакторного теста
np.random.seed(42)
n_samples = 1000
data = pd.DataFrame({
'button_color': np.random.choice(['red', 'blue'], n_samples),
'headline': np.random.choice(['A', 'B'], n_samples),
'layout': np.random.choice(['left', 'right'], n_samples)
})
# Симулируем конверсию с разными эффектами для каждого фактора
data['conversion'] = (
(data['button_color'] == 'red') * 0.05 +
(data['headline'] == 'B') * 0.03 +
(data['layout'] == 'right') * 0.02 +
np.random.normal(0.1, 0.02, n_samples)
)
# Проводим анализ с помощью линейной регрессии
model = ols('conversion ~ C(button_color) + C(headline) + C(layout)', data=data).fit()
print(model.summary())
# Визуализация результатов
plt.figure(figsize=(12, 6))
sm.graphics.plot_partregress_grid(model)
plt.tight_layout()
plt.show()
Этот код проводит многофакторный анализ, используя линейную регрессию:
- Мы симулируем данные с тремя факторами: цвет кнопки, заголовок и макет;
- Создаем модель, учитывающую влияние каждого фактора на конверсию;
- Выводим сводку модели, которая показывает статистическую значимость каждого фактора;
- Визуализируем частичные регрессионные графики для каждого фактора.
Этот подход позволяет нам одновременно оценить влияние нескольких факторов на конверсию и определить, какие изменения наиболее эффективны.
Заключение
В этой статье мы рассмотрели ключевые аспекты веб-аналитики и их применение для оптимизации онлайн-бизнеса. Мы изучили базовые метрики, такие как посещаемость и показатель отказов, а также более сложные показатели, включая расчеты стоимости лида в неделю и месяц, стоимости лида накопленным итогом от указанной даты, расчет процента вовлеченных посетителей, показателей клиентского оттока, ROMI и LTV. Мы также рассмотрели на примерах как проводить когортный анализ и прогнозирование поведения пользователей.
Изучив продуктовые метрики мы перешли к методам машинного обучения в веб-аналитике, включая прогнозирование вероятности конверсии и сегментацию пользователей. Были рассмотрены техники A/B тестирования и многофакторного анализа для оптимизации различных аспектов веб-сайта. Эти инструменты и методы позволяют принимать обоснованные решения для улучшения пользовательского опыта и повышения эффективности онлайн-бизнеса.