Кластеризация пользователей по session duration

Middle Python Медиа

Условие задания

**Контекст:** Медиа-платформа хочет сегментировать аудиторию по паттернам потребления контента для персонализации рекомендаций.

**Данные:** DataFrame `sessions` — колонки: `user_id`, `session_id`, `session_start`, `session_end`, `pages_viewed`, `videos_watched`, `device` (mobile/desktop/tablet), `referrer` (organic/social/direct/email).

**Задание:**
1. Рассчитайте фичи по пользователям: avg/median session duration, sessions per week, avg pages/session, % mobile
2. Кластеризуйте пользователей KMeans (StandardScaler + Elbow)
3. Опишите сегменты и дайте рекомендации по контент-стратегии

Пример данных

Структура для ориентира — реальные значения из эталонного решения.

import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.cluster import KMeans

np.random.seed(42)
n_users = 3000
n_sessions = 40000

# Три типа пользователей (для реалистичности)
user_types = np.random.choice(['casual', 'regular', 'power'], n_users, p=[0.5, 0.35, 0.15])
user_map = {uid: utype for uid, utype in zip(range(n_users), user_types)}

records = []
for i in range(n_sessions):
    uid = np.random.randint(0, n_users)
    utype = user_map[uid]

    if utype == 'casual':
        duration = np.random.exponential(3)  # короткие сессии
        pages = np.random.poisson(2)
        videos = np.random.poisson(0.5)
        device = np.random.choice(['mobile', 'desktop', 'tablet'], p=[0.7, 0.2, 0.1])
    elif utype == 'regular':
        duration = np.random.exponential(12)
        pages = np.random.poisson(6)
        videos = np.random.poisson(2)
        device = np.random.choice(['mobile', 'desktop', 'tablet'], p=[0.5, 0.4, 0.1])
    else:
        duration = np.random.exponential(30)
        pages = np.random.poisson(15)
        videos = np.random.poisson(5)
        device = np.random.choice(['mobile', 'desktop', 'tablet'], p=[0.3, 0.6, 0.1])

    start = pd.Timestamp('2024-01-01') + pd.Timedelta(hours=np.random.randint(0, 2160))
    records.append({
        'user_id': uid, 'session_id': i,
        'session_start': start,
        'session_end': start + pd.Timedelta(minutes=max(0.5, duration)),
        'pages_viewed': max(1, pages),
        'videos_watched': max(0, videos),
        'device': device,
        'referrer': np.random.choice(['organic', 'social', 'direct', 'email'], p=[0.4, 0.3, 0.2, 0.1]),
    })

sessions = pd.DataFrame(records)
sessions['duration_min'] = (
    (sessions['session_end'] - sessions['session_start']).dt.total_seconds() / 60
).round(2)

# 1. Фичи по пользователям
user_features = sessions.groupby('user_id').agg(
    avg_duration=('duration_min', 'mean'),
    median_duration=('duration_min', 'median'),
    session_count=('session_id', 'count'),
    avg_pages=('pages_viewed', 'mean'),
    avg_videos=('videos_watched', 'mean'),
    mobile_share=('device', lambda x: (x == 'mobile').mean()),
).round(3)

# Сессий в неделю (период данных ~90 дней = ~13 недель)
user_features['sessions_per_week'] = (user_features['session_count'] / 13).round(2)

print("Описательная статистика фичей:")
print(user_features.describe().round(2))

# 2. Кластеризация
feature_cols = ['avg_duration', 'median_duration', 'sessions_per_week',
                'avg_pages', 'avg_videos', 'mobile_share']
X = user_features[feature_cols].values

scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# Elbow method
inertias = []
K_range = range(2, 8)
for k in K_range:
    km = KMeans(n_clusters=k, random_state=42, n_init=10)
    km.fit(X_scaled)
    inertias.append(km.inertia_)

print("\nElbow method:")
for k, inertia in zip(K_range, inertias):
    bar = '#' * int(inertia / max(inertias) * 40)
    print(f"  k={k}: {inertia:>10.0f}  {bar}")

# Финальная кластеризация k=3
kmeans = KMeans(n_clusters=3, random_state=42, n_init=10)
user_features['cluster'] = kmeans.fit_predict(X_scaled)

# 3. Профили
profiles = user_features.groupby('cluster')[feature_cols].mean().round(2)
profiles['size'] = user_features['cluster'].value_counts().sort_index()
profiles['share_pct'] = (profiles['size'] / len(user_features) * 100).round(1)

print("\nПрофили кластеров:")
print(profiles)

segment_names = {}
for cluster in range(3):
    p = profiles.loc[cluster]
    if p['avg_duration'] < 5 and p['sessions_per_week'] < 2:
        name = 'Casual Browsers'
        rec = 'Short-form контент, push-уведомления, быстрые форматы'
    elif p['avg_duration'] > 15 and p['avg_videos'] > 3:
        name = 'Power Users'
        rec = 'Эксклюзивный контент, подписка Premium, community'
    else:
        name = 'Regular Readers'
        rec = 'Персонализированные дайджесты, вовлекающие серии статей'

    segment_names[cluster] = name
    print(f"\nCluster {cluster} — {name} ({int(p['size'])} users, {p['share_pct']}%):")
    print(f"  Avg session: {p['avg_duration']:.1f} мин, {p['sessions_per_week']:.1f} сессий/нед")
    print(f"  Pages: {p['avg_pages']:.1f}, Videos: {p['avg_videos']:.1f}, Mobile: {p['mobile_share']*100:.0f}%")
    print(f"  Рекомендация: {rec}")

Темы

pandas sklearn KMeans вовлечённость session StandardScaler elbow

Подсказки

Все тестовые задания →

Частые вопросы

Какой уровень знаний нужен для задачи "Кластеризация пользователей по session duration"?

Это задание для уровня Middle. Для middle-аналитиков с опытом 1-3 года, требует уверенного владения темой и понимания edge cases.

На каких собеседованиях встречается такая задача?

Подобные задания в категории «Python» регулярно дают на собеседованиях аналитика данных в Яндекс, Сбер, Ozon, Авито, Тинькофф, Wildberries, T-Bank, X5, ВТБ и других крупных IT-компаниях. Тематика: pandas, sklearn, KMeans, вовлечённость, session.

Сколько времени даётся на решение?

На реальном собеседовании на подобную задачу отводится 15-30 минут — оцениваются подход, корректность, обработка edge cases. Для тренировки рекомендуем сначала решить самостоятельно, потом сверить с эталонным решением и подсказками.

Где ещё потренироваться по теме «Python»?

На zasqlpython.ru есть 482 Python задачи с проверкой через Pyodide, конспекты Python и pandas, AI мок-собеседование с разбором ваших ответов.

← Все задания