In Python with pandas, two-sample t-test for the sample data takes a few lines, shown below. It returns 1.61e-4.
t = (mean₁ − mean₂) ÷ √(s₁²/n₁ + s₂²/n₂), with Welch–Satterthwaite degrees of freedom
Step by step
- Install the libraries (pip install pandas scipy) and save daily.csv next to your script.
- Run the script and compare the printed value with the expected result.
The code
from scipy import stats
import pandas as pd
df = pd.read_csv("daily.csv")
t, p_value = stats.ttest_ind(df["website_orders"], df["app_orders"], equal_var=False)
print(round(t, 3), p_value)
Expected result on the sample data: 1.61e-4.
What the result means
This compares daily website orders with daily app orders using Welch's version, which does not assume the two groups vary equally. The p-value is far below 0.05, so the gap in averages is very unlikely to be chance.
Notes for Python
- pandas methods such as .std(), .var() and .quantile() match Excel's sample versions (STDEV.S, VAR.S, PERCENTILE.INC). NumPy's np.std() and np.var() default to the population version instead.
- pandas skips NaN values in these calculations by default. Count how many rows were used if data might be missing.
Where two-sample t-test misleads
- Strictly, website and app orders here are paired by day. A paired t-test (T.TEST type 1) is the better choice for paired data; the two-sample version is shown because it is the more common question.
- A small p-value says the difference is probably real, not that it is large or worth acting on. Report the size of the difference too.
- Daily figures that follow a trend are not independent; the test assumes they are.
The plain-language explanation is on the Two-sample t-test page.
The data
| day | website_orders | app_orders |
|---|---|---|
| 1 | 24 | 18 |
| 2 | 27 | 21 |
| 3 | 22 | 19 |
| 4 | 30 | 22 |
| 5 | 28 | 24 |
| 6 | 25 | 20 |
| 7 | 31 | 23 |
| 8 | 29 | 25 |
| 9 | 26 | 22 |
| 10 | 33 | 26 |
| 11 | 30 | 24 |
| 12 | 28 | 23 |
| 13 | 35 | 27 |
| 14 | 32 | 25 |
| 15 | 29 | 24 |
| 16 | 34 | 28 |
| 17 | 61 | 44 |
| 18 | 31 | 26 |
| 19 | 36 | 29 |
| 20 | 33 | 27 |
| 21 | 30 | 25 |
| 22 | 37 | 30 |
| 23 | 35 | 28 |
| 24 | 32 | 27 |
| 25 | 38 | 31 |
| 26 | 36 | 29 |
| 27 | 34 | 28 |
| 28 | 40 | 32 |
| 29 | 37 | 30 |
| 30 | 39 | 33 |
Same method, other tools
Related methods
Learn more about Python
- Python and SQL for data analysis, side by side — 3 min read
- Data analysis methods and techniques, and when to use each — 3 min read
About the data on this page
The figures come from a small made-up dataset, printed above in full so you can check every number by hand. Download it as daily.csv. The results are computed from those rows when the page is built, and the Excel formulas, SQL and Python on these pages are run against the same rows before publishing, so the code and the answers agree.
To get these numbers from your own data without writing formulas, try AnalyzeIt: ask in plain words and it shows the working behind every figure.
Legal entity
Devansh Yadav
Moradabad, Uttar Pradesh
Governing law: Courts at Moradabad, Uttar Pradesh
Phone: +91 8433475698
Legal: legal@analyzeit.in