A + b Con trăn

Trong bài viết này, chúng ta sẽ xem xét quá trình phân tích thử nghiệm A/B, từ việc hình thành giả thuyết, thử nghiệm và cuối cùng là giải thích kết quả. Đối với dữ liệu của chúng tôi, chúng tôi sẽ sử dụng tập dữ liệu từ Kaggle chứa kết quả của thử nghiệm A/B về những gì dường như là 2 thiết kế khác nhau của một trang web (old_page so với. trang mới). Nếu bạn muốn làm theo mã tôi đã sử dụng, vui lòng tải xuống sổ ghi chép jupyter tại trang GitHub của tôi

Đây là những gì chúng ta sẽ làm

Để làm cho nó thực tế hơn một chút, đây là một kịch bản tiềm năng cho nghiên cứu của chúng tôi

Hãy tưởng tượng bạn làm việc trong nhóm sản phẩm tại một doanh nghiệp thương mại điện tử trực tuyến cỡ trung bình. Nhà thiết kế UX đã làm việc rất chăm chỉ trên phiên bản mới của trang sản phẩm, với hy vọng rằng nó sẽ dẫn đến tỷ lệ chuyển đổi cao hơn. Người quản lý sản phẩm (PM) nói với bạn rằng tỷ lệ chuyển đổi hiện tại trung bình là khoảng 13% trong cả năm và nhóm sẽ hài lòng với mức tăng 2%, nghĩa là thiết kế mới sẽ được coi là thành công nếu nó tăng

Trước khi triển khai thay đổi, nhóm sẽ cảm thấy thoải mái hơn khi thử nghiệm thay đổi đó trên một số ít người dùng để xem nó hoạt động như thế nào, vì vậy, bạn nên chạy thử nghiệm A/B trên một nhóm nhỏ người dùng cơ sở người dùng của mình

1. Thiết kế thí nghiệm của chúng tôi

Xây dựng một giả thuyết

Trước tiên, chúng tôi muốn đảm bảo rằng chúng tôi đưa ra một giả thuyết khi bắt đầu dự án của mình. Điều này sẽ đảm bảo việc giải thích kết quả của chúng tôi là chính xác cũng như nghiêm ngặt.

Vì chúng tôi không biết liệu thiết kế mới sẽ hoạt động tốt hơn hay tệ hơn (hoặc giống?) như thiết kế hiện tại của chúng tôi, chúng tôi sẽ chọn thử nghiệm hai đầu

Hₒ. p = pₒ

Hₐ. p ≠ pₒ

trong đó p và pₒ lần lượt là tỷ lệ chuyển đổi của thiết kế mới và cũ. Chúng tôi cũng sẽ đặt mức tin cậy là 95%

a = 0. 05

Giá trị α là ngưỡng mà chúng tôi đặt, theo đó chúng tôi nói “nếu xác suất quan sát thấy một kết quả cực đoan trở lên (giá trị p) thấp hơn α, thì chúng tôi bác bỏ giả thuyết Null”. Vì α=0 của chúng ta. 05 (biểu thị xác suất 5%), độ tin cậy của chúng tôi (1 — α) là 95%

Đừng lo lắng nếu bạn không quen thuộc với những điều trên, tất cả điều này thực sự có nghĩa là bất kể tỷ lệ chuyển đổi nào mà chúng tôi quan sát được cho thiết kế mới trong thử nghiệm của mình, chúng tôi muốn chắc chắn 95% rằng nó khác biệt về mặt thống kê so với tỷ lệ chuyển đổi của thiết kế cũ của chúng tôi

Lựa chọn các biến

Đối với thử nghiệm của chúng tôi, chúng tôi sẽ cần hai nhóm

  • Một nhóm
    df = pd.read_csv('ab_data.csv')

    df.head()
    1 - Họ sẽ được xem thiết kế cũ
  • Một nhóm
    df = pd.read_csv('ab_data.csv')

    df.head()
    2 (hoặc thử nghiệm) - Họ sẽ được xem thiết kế mới

Đây sẽ là Biến độc lập của chúng tôi. Lý do chúng tôi có hai nhóm mặc dù chúng tôi biết tỷ lệ chuyển đổi cơ bản là vì chúng tôi muốn kiểm soát các biến số khác có thể ảnh hưởng đến kết quả của chúng tôi, chẳng hạn như tính thời vụ. bằng cách có một nhóm

df = pd.read_csv('ab_data.csv')

df.head()
1, chúng tôi có thể so sánh trực tiếp kết quả của họ với nhóm
df = pd.read_csv('ab_data.csv')

df.head()
2, bởi vì sự khác biệt hệ thống duy nhất giữa các nhóm là thiết kế của trang sản phẩm và do đó chúng tôi có thể quy bất kỳ sự khác biệt nào về kết quả cho các thiết kế

Đối với Biến phụ thuộc của chúng tôi (i. e. những gì chúng tôi đang cố gắng đo lường), chúng tôi quan tâm đến việc nắm bắt

df = pd.read_csv('ab_data.csv')

df.head()
5. Một cách chúng ta có thể viết mã này là theo từng phiên người dùng với một biến nhị phân

  • df = pd.read_csv('ab_data.csv')

    df.head()
    6 - Người dùng không mua sản phẩm trong phiên người dùng này
  • df = pd.read_csv('ab_data.csv')

    df.head()
    7 - Người dùng đã mua sản phẩm trong phiên người dùng này

Bằng cách này, chúng ta có thể dễ dàng tính giá trị trung bình cho từng nhóm để có được tỷ lệ chuyển đổi của từng thiết kế

Chọn cỡ mẫu

Điều quan trọng cần lưu ý là vì chúng tôi sẽ không kiểm tra toàn bộ cơ sở người dùng (dân số của chúng tôi), tỷ lệ chuyển đổi mà chúng tôi nhận được chắc chắn sẽ chỉ là ước tính của tỷ lệ thực

Số người (hoặc phiên người dùng) mà chúng tôi quyết định nắm bắt trong mỗi nhóm sẽ ảnh hưởng đến độ chính xác của tỷ lệ chuyển đổi ước tính của chúng tôi. cỡ mẫu càng lớn, ước tính của chúng tôi càng chính xác (i. e. khoảng tin cậy của chúng tôi càng nhỏ), cơ hội phát hiện sự khác biệt trong hai nhóm càng cao, nếu có

Mặt khác, mẫu của chúng tôi càng lớn thì nghiên cứu của chúng tôi càng trở nên đắt đỏ (và không thực tế).

Vậy chúng ta nên có bao nhiêu người trong mỗi nhóm?

Kích thước mẫu mà chúng tôi cần được ước tính thông qua một thứ gọi là Phân tích sức mạnh và nó phụ thuộc vào một số yếu tố

  • Sức mạnh của thử nghiệm (1 — β) — Điều này thể hiện xác suất tìm thấy sự khác biệt thống kê giữa các nhóm trong thử nghiệm của chúng tôi khi thực sự có sự khác biệt. Điều này thường được đặt ở 0. 8 theo quy ước (đây là thông tin thêm về sức mạnh thống kê, nếu bạn tò mò)
  • Giá trị alpha (α) — Giá trị tới hạn mà chúng tôi đã đặt trước đó thành 0. 05
  • Kích thước hiệu ứng — Mức độ khác biệt mà chúng tôi dự kiến ​​sẽ có giữa các tỷ lệ chuyển đổi

Vì nhóm của chúng tôi sẽ hài lòng với mức chênh lệch là 2%, chúng tôi có thể sử dụng 13% và 15% để tính kích thước hiệu ứng mà chúng tôi mong đợi

May mắn thay, Python đảm nhận tất cả các tính toán này cho chúng tôi

# Packages imports
import numpy as np
import pandas as pd
import scipy.stats as stats
import statsmodels.stats.api as sms
import matplotlib as mpl
import matplotlib.pyplot as plt
import seaborn as sns
from math import ceil

%matplotlib inline

# Some plot styling preferences
plt.style.use('seaborn-whitegrid')
font = {'family' : 'Helvetica',
'weight' : 'bold',
'size' : 14}

mpl.rc('font', **font)
effect_size = sms.proportion_effectsize(0.13, 0.15) # Calculating effect size based on our expected rates

required_n = sms.NormalIndPower().solve_power(
effect_size,
power=0.8,
alpha=0.05,
ratio=1
) # Calculating sample size needed

required_n = ceil(required_n) # Rounding up to next whole number

print(required_n)

df = pd.read_csv('ab_data.csv')

df.head()
8

Chúng tôi cần ít nhất 4720 quan sát cho mỗi nhóm

Đã đặt tham số

df = pd.read_csv('ab_data.csv')

df.head()
9 thành 0. 8 trong thực tế có nghĩa là nếu có sự khác biệt thực tế về tỷ lệ chuyển đổi giữa các thiết kế của chúng tôi, thì giả sử sự khác biệt là tỷ lệ chúng tôi ước tính (13% so với. 15%), chúng tôi có khoảng 80% cơ hội phát hiện nó có ý nghĩa thống kê trong thử nghiệm của chúng tôi với kích thước mẫu mà chúng tôi đã tính toán

2. Thu thập và chuẩn bị dữ liệu

Công cụ tuyệt vời. Vì vậy, bây giờ chúng tôi có kích thước mẫu cần thiết, chúng tôi cần thu thập dữ liệu. Thông thường tại thời điểm này, bạn sẽ làm việc với nhóm của mình để thiết lập thử nghiệm, có thể là với sự trợ giúp của nhóm Kỹ thuật và đảm bảo rằng bạn thu thập đủ dữ liệu dựa trên kích thước mẫu cần thiết

Tuy nhiên, vì chúng tôi sẽ sử dụng tập dữ liệu mà chúng tôi tìm thấy trực tuyến, để mô phỏng tình huống này, chúng tôi sẽ

  1. Tải xuống tập dữ liệu từ Kaggle
  2. Đọc dữ liệu vào DataFrame của gấu trúc
  3. Kiểm tra và làm sạch dữ liệu khi cần thiết
  4. Lấy mẫu ngẫu nhiên
    df.info()<class 'pandas.core.frame.DataFrame'>
    RangeIndex: 294478 entries, 0 to 294477
    Data columns (total 5 columns):
    # Column Non-Null Count Dtype
    --- ------ -------------- -----
    0 user_id 294478 non-null int64
    1 timestamp 294478 non-null object
    2 group 294478 non-null object
    3 landing_page 294478 non-null object
    4 converted 294478 non-null int64
    dtypes: int64(2), object(3)
    memory usage: 11.2+ MB
    # To make sure all the control group are seeing the old page and viceversa

    pd.crosstab(df['group'], df['landing_page'])
    0 hàng từ DataFrame cho mỗi nhóm *

*Ghi chú. Thông thường chúng ta không cần thực hiện bước 4, đây chỉ là để làm bài tập thôi.

Vì tôi đã tải xuống bộ dữ liệu, tôi sẽ đi thẳng đến số 2

df = pd.read_csv('ab_data.csv')

df.head()

png

df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 294478 entries, 0 to 294477
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 user_id 294478 non-null int64
1 timestamp 294478 non-null object
2 group 294478 non-null object
3 landing_page 294478 non-null object
4 converted 294478 non-null int64
dtypes: int64(2), object(3)
memory usage: 11.2+ MB
# To make sure all the control group are seeing the old page and viceversa

pd.crosstab(df['group'], df['landing_page'])

png

Có 294478 hàng trong DataFrame, mỗi hàng đại diện cho một phiên người dùng, cũng như 5 cột

  • df.info()<class 'pandas.core.frame.DataFrame'>
    RangeIndex: 294478 entries, 0 to 294477
    Data columns (total 5 columns):
    # Column Non-Null Count Dtype
    --- ------ -------------- -----
    0 user_id 294478 non-null int64
    1 timestamp 294478 non-null object
    2 group 294478 non-null object
    3 landing_page 294478 non-null object
    4 converted 294478 non-null int64
    dtypes: int64(2), object(3)
    memory usage: 11.2+ MB
    # To make sure all the control group are seeing the old page and viceversa

    pd.crosstab(df['group'], df['landing_page'])
    1 - ID người dùng của mỗi phiên
  • df.info()<class 'pandas.core.frame.DataFrame'>
    RangeIndex: 294478 entries, 0 to 294477
    Data columns (total 5 columns):
    # Column Non-Null Count Dtype
    --- ------ -------------- -----
    0 user_id 294478 non-null int64
    1 timestamp 294478 non-null object
    2 group 294478 non-null object
    3 landing_page 294478 non-null object
    4 converted 294478 non-null int64
    dtypes: int64(2), object(3)
    memory usage: 11.2+ MB
    # To make sure all the control group are seeing the old page and viceversa

    pd.crosstab(df['group'], df['landing_page'])
    2 - Dấu thời gian cho phiên
  • df.info()<class 'pandas.core.frame.DataFrame'>
    RangeIndex: 294478 entries, 0 to 294477
    Data columns (total 5 columns):
    # Column Non-Null Count Dtype
    --- ------ -------------- -----
    0 user_id 294478 non-null int64
    1 timestamp 294478 non-null object
    2 group 294478 non-null object
    3 landing_page 294478 non-null object
    4 converted 294478 non-null int64
    dtypes: int64(2), object(3)
    memory usage: 11.2+ MB
    # To make sure all the control group are seeing the old page and viceversa

    pd.crosstab(df['group'], df['landing_page'])
    3 - Người dùng được chỉ định vào nhóm nào trong phiên đó {
    df = pd.read_csv('ab_data.csv')

    df.head()
    1,
    df = pd.read_csv('ab_data.csv')

    df.head()
    2}
  • df.info()<class 'pandas.core.frame.DataFrame'>
    RangeIndex: 294478 entries, 0 to 294477
    Data columns (total 5 columns):
    # Column Non-Null Count Dtype
    --- ------ -------------- -----
    0 user_id 294478 non-null int64
    1 timestamp 294478 non-null object
    2 group 294478 non-null object
    3 landing_page 294478 non-null object
    4 converted 294478 non-null int64
    dtypes: int64(2), object(3)
    memory usage: 11.2+ MB
    # To make sure all the control group are seeing the old page and viceversa

    pd.crosstab(df['group'], df['landing_page'])
    6 - Mỗi người dùng đã xem thiết kế nào trong phiên đó {
    df.info()<class 'pandas.core.frame.DataFrame'>
    RangeIndex: 294478 entries, 0 to 294477
    Data columns (total 5 columns):
    # Column Non-Null Count Dtype
    --- ------ -------------- -----
    0 user_id 294478 non-null int64
    1 timestamp 294478 non-null object
    2 group 294478 non-null object
    3 landing_page 294478 non-null object
    4 converted 294478 non-null int64
    dtypes: int64(2), object(3)
    memory usage: 11.2+ MB
    # To make sure all the control group are seeing the old page and viceversa

    pd.crosstab(df['group'], df['landing_page'])
    7,
    df.info()<class 'pandas.core.frame.DataFrame'>
    RangeIndex: 294478 entries, 0 to 294477
    Data columns (total 5 columns):
    # Column Non-Null Count Dtype
    --- ------ -------------- -----
    0 user_id 294478 non-null int64
    1 timestamp 294478 non-null object
    2 group 294478 non-null object
    3 landing_page 294478 non-null object
    4 converted 294478 non-null int64
    dtypes: int64(2), object(3)
    memory usage: 11.2+ MB
    # To make sure all the control group are seeing the old page and viceversa

    pd.crosstab(df['group'], df['landing_page'])
    8}
  • df.info()<class 'pandas.core.frame.DataFrame'>
    RangeIndex: 294478 entries, 0 to 294477
    Data columns (total 5 columns):
    # Column Non-Null Count Dtype
    --- ------ -------------- -----
    0 user_id 294478 non-null int64
    1 timestamp 294478 non-null object
    2 group 294478 non-null object
    3 landing_page 294478 non-null object
    4 converted 294478 non-null int64
    dtypes: int64(2), object(3)
    memory usage: 11.2+ MB
    # To make sure all the control group are seeing the old page and viceversa

    pd.crosstab(df['group'], df['landing_page'])
    9 - Phiên có kết thúc với chuyển đổi hay không (nhị phân,
    df = pd.read_csv('ab_data.csv')

    df.head()
    6=không chuyển đổi,
    df = pd.read_csv('ab_data.csv')

    df.head()
    7=đã chuyển đổi)

Chúng tôi thực sự sẽ chỉ sử dụng các cột

df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 294478 entries, 0 to 294477
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 user_id 294478 non-null int64
1 timestamp 294478 non-null object
2 group 294478 non-null object
3 landing_page 294478 non-null object
4 converted 294478 non-null int64
dtypes: int64(2), object(3)
memory usage: 11.2+ MB
# To make sure all the control group are seeing the old page and viceversa

pd.crosstab(df['group'], df['landing_page'])
3 và
df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 294478 entries, 0 to 294477
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 user_id 294478 non-null int64
1 timestamp 294478 non-null object
2 group 294478 non-null object
3 landing_page 294478 non-null object
4 converted 294478 non-null int64
dtypes: int64(2), object(3)
memory usage: 11.2+ MB
# To make sure all the control group are seeing the old page and viceversa

pd.crosstab(df['group'], df['landing_page'])
9 để phân tích

Trước khi chúng tôi tiếp tục và lấy mẫu dữ liệu để lấy tập hợp con của mình, hãy đảm bảo rằng không có người dùng nào đã được lấy mẫu nhiều lần

session_counts = df['user_id'].value_counts(ascending=False)
multi_users = session_counts[session_counts > 1].count()

print(f'There are {multi_users} users that appear multiple times in the dataset')

session_counts = df['user_id'].value_counts(ascending=False)
multi_users = session_counts[session_counts > 1].count()

print(f'There are {multi_users} users that appear multiple times in the dataset')
4

Trên thực tế, có 3894 người dùng xuất hiện nhiều lần. Vì số lượng khá thấp nên chúng tôi sẽ tiếp tục và xóa chúng khỏi DataFrame để tránh lấy mẫu hai lần cho cùng một người dùng

users_to_drop = session_counts[session_counts > 1].index

df = df[~df['user_id'].isin(users_to_drop)]
print(f'The updated dataset now has {df.shape[0]} entries')

session_counts = df['user_id'].value_counts(ascending=False)
multi_users = session_counts[session_counts > 1].count()

print(f'There are {multi_users} users that appear multiple times in the dataset')
5

Lấy mẫu

Giờ đây, Khung dữ liệu của chúng tôi đã đẹp và sạch sẽ, chúng tôi có thể tiếp tục và lấy mẫu các mục nhập

df.info()<class 'pandas.core.frame.DataFrame'>
RangeIndex: 294478 entries, 0 to 294477
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 user_id 294478 non-null int64
1 timestamp 294478 non-null object
2 group 294478 non-null object
3 landing_page 294478 non-null object
4 converted 294478 non-null int64
dtypes: int64(2), object(3)
memory usage: 11.2+ MB
# To make sure all the control group are seeing the old page and viceversa

pd.crosstab(df['group'], df['landing_page'])
0 cho mỗi nhóm. Chúng tôi có thể sử dụng phương pháp
session_counts = df['user_id'].value_counts(ascending=False)
multi_users = session_counts[session_counts > 1].count()

print(f'There are {multi_users} users that appear multiple times in the dataset')
7 của gấu trúc để thực hiện việc này, phương pháp này sẽ thực hiện Lấy mẫu ngẫu nhiên đơn giản cho chúng tôi

Ghi chú. Tôi đã đặt

session_counts = df['user_id'].value_counts(ascending=False)
multi_users = session_counts[session_counts > 1].count()

print(f'There are {multi_users} users that appear multiple times in the dataset')
8 để kết quả có thể lặp lại nếu bạn muốn theo dõi trên Notebook của mình. chỉ cần sử dụng
session_counts = df['user_id'].value_counts(ascending=False)
multi_users = session_counts[session_counts > 1].count()

print(f'There are {multi_users} users that appear multiple times in the dataset')
8 trong chức năng của bạn và bạn sẽ nhận được mẫu giống như tôi đã làm

control_sample = df[df['group'] == 'control'].sample(n=required_n, random_state=22)
treatment_sample = df[df['group'] == 'treatment'].sample(n=required_n, random_state=22)

ab_test = pd.concat([control_sample, treatment_sample], axis=0)
ab_test.reset_index(drop=True, inplace=True)
ab_test

png

ab_test.info()

users_to_drop = session_counts[session_counts > 1].index

df = df[~df['user_id'].isin(users_to_drop)]
print(f'The updated dataset now has {df.shape[0]} entries')
0

ab_test['group'].value_counts()

users_to_drop = session_counts[session_counts > 1].index

df = df[~df['user_id'].isin(users_to_drop)]
print(f'The updated dataset now has {df.shape[0]} entries')
1

Tuyệt vời, có vẻ như mọi thứ đã diễn ra theo đúng kế hoạch và chúng tôi hiện đã sẵn sàng để phân tích kết quả của mình

3. Trực quan hóa kết quả

Điều đầu tiên chúng ta có thể làm là tính toán một số thống kê cơ bản để có ý tưởng về các mẫu của chúng ta trông như thế nào

conversion_rates = ab_test.groupby('group')['converted']

std_p = lambda x: np.std(x, ddof=0) # Std. deviation of the proportion
se_p = lambda x: stats.sem(x, ddof=0) # Std. error of the proportion (std / sqrt(n))

conversion_rates = conversion_rates.agg([np.mean, std_p, se_p])
conversion_rates.columns = ['conversion_rate', 'std_deviation', 'std_error']


conversion_rates.style.format('{:.3f}')

png

Đánh giá theo các số liệu thống kê ở trên, có vẻ như hai thiết kế của chúng tôi hoạt động rất giống nhau, với thiết kế mới của chúng tôi hoạt động tốt hơn một chút, khoảng. 12. 3% so với. 12. tỷ lệ chuyển đổi 6%

Vẽ sơ đồ dữ liệu sẽ làm cho những kết quả này dễ nắm bắt hơn

plt.figure(figsize=(8,6))

sns.barplot(x=ab_test['group'], y=ab_test['converted'], ci=False)

plt.ylim(0, 0.17)
plt.title('Conversion rate by group', pad=20)
plt.xlabel('Group', labelpad=15)
plt.ylabel('Converted (proportion)', labelpad=15);

png

Tỷ lệ chuyển đổi cho các nhóm của chúng tôi thực sự rất gần. Cũng xin lưu ý rằng tỷ lệ chuyển đổi của nhóm

df = pd.read_csv('ab_data.csv')

df.head()
1 thấp hơn so với những gì chúng tôi mong đợi dựa trên những gì chúng tôi biết về mức trung bình của chúng tôi. tỷ lệ chuyển đổi (12. 3% so với. 13%). Điều này cho thấy rằng có một số thay đổi trong kết quả khi lấy mẫu từ dân số

Vì vậy… giá trị của nhóm

df = pd.read_csv('ab_data.csv')

df.head()
2 cao hơn. Sự khác biệt này có ý nghĩa thống kê không?

4. Kiểm tra giả thuyết

Bước cuối cùng của phân tích của chúng tôi là kiểm tra giả thuyết của chúng tôi. Vì chúng tôi có một mẫu rất lớn, chúng tôi có thể sử dụng để tính giá trị p của mình (i. e. kiểm tra z)

Một lần nữa, Python thực hiện tất cả các phép tính rất dễ dàng. Chúng ta có thể sử dụng mô-đun

users_to_drop = session_counts[session_counts > 1].index

df = df[~df['user_id'].isin(users_to_drop)]
print(f'The updated dataset now has {df.shape[0]} entries')
4 để lấy giá trị p và khoảng tin cậy

df = pd.read_csv('ab_data.csv')

df.head()
0

users_to_drop = session_counts[session_counts > 1].index

df = df[~df['user_id'].isin(users_to_drop)]
print(f'The updated dataset now has {df.shape[0]} entries')
5

5. Rút ra kết luận

Vì giá trị p của chúng tôi = 0. 732 cao hơn nhiều so với α=0 của chúng tôi. 05, chúng tôi không thể bác bỏ giả thuyết Null Hₒ, điều đó có nghĩa là thiết kế mới của chúng tôi không hoạt động khác biệt đáng kể (chứ chưa nói đến tốt hơn) so với thiết kế cũ của chúng tôi. (

Ngoài ra, nếu chúng ta xem xét khoảng tin cậy cho nhóm

df = pd.read_csv('ab_data.csv')

df.head()
2 ([0. 116, 0. 135], hoặc 11. 6-13. 5%) chúng tôi nhận thấy rằng

  1. Nó bao gồm giá trị cơ sở của chúng tôi về tỷ lệ chuyển đổi 13%
  2. Nó không bao gồm giá trị mục tiêu của chúng tôi là 15% (mức tăng 2% mà chúng tôi đang hướng tới)

Điều này có nghĩa là nhiều khả năng tỷ lệ chuyển đổi thực sự của thiết kế mới tương tự như đường cơ sở của chúng tôi, thay vì mục tiêu 15% mà chúng tôi đã hy vọng. Đây là bằng chứng nữa cho thấy thiết kế mới của chúng tôi không có khả năng là một cải tiến so với thiết kế cũ của chúng tôi và thật không may, chúng tôi đang quay lại bảng vẽ

B += A trong Python là gì?

Biểu thức a + b tính toán một danh sách mới từ các đối tượng được liên kết với a và b , không bị sửa đổi . Khi bạn gán lại giá trị này cho a , bạn thay đổi liên kết của một biến để trỏ đến giá trị mới.

A là gì

-= Phép trừ . Subtracts a value from the variable and assigns the result to that variable.

7 toán tử trong Python là gì?

Toán tử Python .
toán tử số học
Toán tử gán
Toán tử so sánh
Toán tử logic
Toán tử nhận dạng
nhà khai thác thành viên
Toán tử bitwise

a =+ B có hoạt động trong Python không?

Trong python a += b không phải lúc nào cũng hoạt động giống như a = a + b , cùng một toán hạng có thể cho kết quả khác nhau . Nhưng để hiểu tại sao chúng thể hiện các hành vi khác nhau, bạn phải đi sâu vào hoạt động của các biến.