ETL (Extract, Transform, Load) — это процесс извлечения, преобразования и загрузки данных, который часто используется при обработке и подготовке данных для анализа, включая задачи A/B тестирования. В контексте A/B тестов на Python, ETL позволяет собрать данные из различных источников (например, систем аналитики, баз данных или CSV-файлов), привести их в удобный для анализа формат и затем загрузить в хранилище для последующего изучения.
Основные этапы ETL для A/B тестирования на Python:
- Извлечение (Extract): На этом этапе данные загружаются из источников. В A/B тестировании это могут быть данные о взаимодействии пользователей (например, клики, покупки) из систем аналитики или баз данных. В Python популярными библиотеками для этого этапа являются pandas (для чтения файлов CSV или Excel), SQLAlchemy (для взаимодействия с SQL базами данных), а также requests и BeautifulSoup (для загрузки данных из API или веб-страниц).
- Преобразование (Transform): Здесь данные очищаются и подготавливаются к анализу. Например, можно преобразовать временные метки, заполнить пропущенные значения, создать новые признаки (например, вычислить разницу конверсий между версиями), а также удалить дублирующиеся или нерелевантные строки. Для обработки данных на этом этапе широко используется библиотека pandas, которая поддерживает фильтрацию, агрегацию, изменение типов данных и другие трансформации.
- Загрузка (Load): На финальном этапе данные загружаются в хранилище, откуда они будут использованы для анализа. Это может быть база данных, облачное хранилище, либо локальный CSV-файл. Например, данные могут быть записаны в SQL базу данных для дальнейшей обработки или анализа с помощью инструментов BI.
ETL на Python помогает подготовить данные для дальнейшего анализа эффективности разных версий в A/B тестировании, что позволяет маркетологам и аналитикам принимать обоснованные решения.
Пример ETL процесса на Python для A/B теста:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import pandas as pd from sqlalchemy import create_engine # Извлечение данных из CSV data_a = pd.read_csv('version_a.csv') data_b = pd.read_csv('version_b.csv') # Преобразование данных data_a['converted'] = data_a['actions'] > 0 # Пример создания бинарного признака data_b['converted'] = data_b['actions'] > 0 data_a.dropna(inplace=True) # Удаление пропусков data_b.dropna(inplace=True) # Объединение данных для последующего анализа data = pd.concat([data_a, data_b]) # Загрузка в SQL базу данных engine = create_engine('sqlite:///ab_test_data.db') data.to_sql('ab_test_results', con=engine, if_exists='replace') |
Пример 2
Давайте реализуем A/B-тестирование на Python на примере набора данных. Этот набор данных можно скачать здесь.
1 2 3 4 5 6 7 8 9 10 | import numpy as np import pandas as pd import scipy.stats as stats import statsmodels.stats.api as sms import seaborn as sns from math import ceil # Load dataset df = pd.read_csv('ab_data.csv') df.head() |
Output:
1 2 3 4 5 6 7 | | index | user_id | timestamp | group | landing_page | converted | |:-----:|:--------:|:---------------------------:|:---------:|:-------------:|:---------:| | 0 | 851104 | 2017-01-21 22:11:48.556739 | control | old_page | 0.0 | | 1 | 804228 | 2017-01-12 08:01:45.159739 | control | old_page | 0.0 | | 2 | 661590 | 2017-01-11 16:55:06.154213 | treatment | new_page | 0.0 | | 3 | 853541 | 2017-01-08 18:28:03.143765 | treatment | new_page | 0.0 | | 4 | 864975 | 2017-01-21 01:52:26.210827 | control | old_page | 1.0 | |
Этот набор данных содержит идентификаторы пользователей, метку времени сеанса доступа к целевой странице и информацию о том, принадлежит ли пользователь к контрольной или преобразуемой группе. Этот набор данных содержит данные нескольких сеансов для некоторых пользователей. Мы удалим пользователей с несколькими сеансами из нашего тестирования.
1 2 3 4 5 6 7 8 | # Users with multiple session counts session_counts = df['user_id'].value_counts(ascending = False) multi_users = session_counts[session_counts > 1].count() # dropping with multiple session counts users_to_drop = session_counts[session_counts > 1].index df = df[~ df['user_id'].isin(users_to_drop)] |
Затем мы случайным образом выберем данные 5000 пользователей из каждой группы и проведем тест статистической значимости.
1 2 3 4 5 6 7 8 9 10 11 | # Sample control and treatment group control_sample = df[df['group'] == 'control'].sample(n = 5000, random_state = 12) treatment_sample = df[df['group'] == 'treatment'].sample(n = 5000, random_state = 12) ab_test = pd.concat([control_sample, treatment_sample], axis=0) ab_test.reset_index(drop=True, inplace=True) # Define functions for standard deviation and standard error std_dev = lambda x : np.std(x, ddof = 0) std_error = lambda x : stats.sem(x, ddof = 0) conversion_rate = ab_test.groupby('group')['converted'].agg([np.mean, std_dev, std_error]) conversion_rate.columns = ['conversion_rate', 'std_deviation', 'std_error'] conversion_rate |
Output
1 2 3 4 | | group | conversion_rate | std_deviation | std_error | |:---------:|:----------------:|:--------------:|:----------:| | control | 0.1114 | 0.318296 | 0.004501 | | treatment | 0.1218 | 0.327055 | 0.004625 | |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | from statsmodels.stats.proportion import proportions_ztest, proportion_confint control_results = ab_test[ab_test['group'] == 'control']['converted'] treatment_results = ab_test[ab_test['group'] == 'treatment']['converted'] num_control = control_results.count() num_treatment = treatment_results.count() successes = [control_results.sum(), treatment_results.sum()] nobs = [num_control, num_treatment] z_stat, pval = proportions_ztest(successes, nobs = nobs) (lower_con, lower_treat), (upper_con, upper_treat) = proportion_confint(successes, nobs=nobs, alpha=0.05) print(f'Z Statistic - {z_stat:.2f}') print(f'P-Value - {pval:.3f}') print(f'CI 95% for control group - [{lower_con:.3f}, {upper_con:.3f}]') print(f'CI 95% for treatment group - [{lower_treat:.3f}, {upper_treat:.3f}]') |
Output
1 2 3 4 | Z Statistic - -1.15 P-Value - 0.252 CI 95% for control group - [0.106, 0.123] CI 95% for treatment group - [0.113, 0.131] |
Как видите, значение p для результатов A/B-тестирования составляет 0,252. Если мы установим уровень значимости 0,05, то мы не сможем отвергнуть НУЛЕВУЮ гипотезу при этом значении p. Это означает, что наблюдаемые результаты произошли случайно и не являются статистически значимыми, чтобы сказать, что целевая страница экспериментальной группы работает лучше.
Итак,
- A/B-тестирование сравнивает две версии продукта, веб-сайта, приложения или маркетинговой кампании, чтобы определить, какая из них работает лучше. Это полезно в ситуации, когда вы хотите проверить эффективность дополнительных изменений в продукте, веб-сайте или приложении.
- После проведения A/B-тестирования нам необходимо доказать, что результаты статистически значимы. Это означает, что наблюдаемые результаты не являются случайными
Comments
Post a Comment