Python Track

pandas, NumPy, and SciPy for Biology Data

This page teaches the Python workflow directly: read a dataset, clean it, summarize groups, run statistical tests, and interpret the result for an EBS poster.

Lesson 1

The Python Mental Model

Python analysis is a conversation between a table and a question. Your job is to keep each step visible: load the data, inspect it, clean it, summarize it, test it, and write down what the result means.

Three Libraries, Three Jobs

  • pandas handles tables. A pandas table is called a DataFrame.
  • NumPy handles numeric arrays and calculations.
  • SciPy handles statistical tests and scientific computations.

Teacher note: Do not start with a statistical test. Start by asking, "What is one row? What does each column mean? Which rows should be compared?"

Command Reference

Useful Python Libraries and Commands

You do not need every Python library. For most EBS dry-lab projects, start with pandas for tables, NumPy for numeric calculations, and SciPy for statistics. Add other libraries only when the research question genuinely needs them.

Which Libraries Are Useful?

LibraryUse it forWhen it matters in biology research
pandasTables, CSV files, cleaning, filtering, grouping, mergingAny project with sample metadata, public-health tables, experiment results, or spreadsheet-like data
NumPyArrays, numeric calculations, means, standard deviations, percentilesWhen columns need mathematical operations or you need clean numeric inputs for statistics
SciPyStatistical tests, correlations, probability distributions, scientific calculationsWhen you need a t-test, chi-square test, Mann-Whitney U test, correlation, or regression helper
matplotlibCore plottingWhen you need a poster figure and want full control over labels, axes, and export size
seabornCleaner statistical plots built on matplotlibWhen you want fast box plots, violin plots, scatter plots, and regression-style visual summaries
BiopythonSequence and biological file handlingWhen your project uses FASTA files, sequence records, or biological database formats
statsmodelsMore detailed statistical modelsWhen you need regression tables, confidence intervals, or model diagnostics beyond SciPy basics
scikit-learnMachine learningOnly when prediction is truly part of the project; not needed for basic EBS statistics

Teacher note: If you are new, do not start with machine learning. Most strong beginner projects use pandas, NumPy, SciPy, and one clear figure.

Most Useful pandas Commands

CommandWhat it doesExample
pd.read_csv()Loads a CSV file into a DataFramedf = pd.read_csv("enzyme_activity.csv")
df.head()Shows the first rows so you can inspect the tabledf.head()
df.shapeReports row and column countdf.shape
df.columnsLists column namesdf.columns
df.info()Shows column types and missing-value countsdf.info()
df.describe()Summarizes numeric columnsdf.describe()
df["column"]Selects one columndf["enzyme_activity"]
df.loc[]Selects rows and columns by label or conditiondf.loc[df["condition"] == "control"]
df.query()Filters rows using a readable expressiondf.query("temperature_c == 39")
df.value_counts()Counts categories or repeated valuesdf["condition"].value_counts()
df.isna().sum()Counts missing values by columndf.isna().sum()
df.dropna()Removes rows with missing datadf.dropna(subset=["enzyme_activity"])
df.fillna()Fills missing values when justifieddf["ph"].fillna(df["ph"].median())
df.rename()Renames confusing columnsdf.rename(columns={"ph": "pH"})
df.astype()Changes a column typedf["temperature_c"].astype(float)
df.groupby()Splits data into groups before summarizingdf.groupby("condition")["enzyme_activity"].mean()
.agg()Runs several summaries at once.agg(["count", "mean", "std"])
df.sort_values()Sorts rowsdf.sort_values("enzyme_activity")
pd.merge()Combines two tables by a shared keypd.merge(samples, metadata, on="sample_id")
df.to_csv()Saves a cleaned tableclean.to_csv("cleaned.csv", index=False)

Most Useful NumPy Commands

CommandWhat it doesExample
np.array()Creates a numeric arrayvalues = np.array([11.2, 10.8, 11.5])
np.mean()Calculates the meannp.mean(control)
np.median()Calculates the mediannp.median(control)
np.std()Calculates standard deviationnp.std(control, ddof=1)
np.min() / np.max()Finds smallest and largest valuesnp.max(treatment)
np.percentile()Finds percentile cutoffsnp.percentile(control, [25, 50, 75])
np.where()Creates conditional valuesnp.where(values > 12, "high", "low")
np.isnan()Detects missing numeric valuesnp.isnan(values)
np.unique()Finds unique values and countsnp.unique(groups, return_counts=True)
np.corrcoef()Calculates a correlation matrixnp.corrcoef(temp, activity)
np.random.seed()Makes random work reproduciblenp.random.seed(42)

Most Useful SciPy Commands

CommandWhat it doesExample
stats.ttest_ind()Compares two independent group meansstats.ttest_ind(control, treatment, equal_var=False)
stats.ttest_rel()Compares paired measurementsstats.ttest_rel(before, after)
stats.mannwhitneyu()Compares two groups without assuming normalitystats.mannwhitneyu(control, treatment)
stats.chi2_contingency()Tests association between categorical variablesstats.chi2_contingency(table)
stats.fisher_exact()Tests small 2x2 categorical tablesstats.fisher_exact(table)
stats.pearsonr()Measures linear correlation between two numeric variablesstats.pearsonr(temp, activity)
stats.spearmanr()Measures rank correlationstats.spearmanr(dose, response)
stats.linregress()Fits a simple linear regressionstats.linregress(temp, activity)
stats.shapiro()Checks normality for small samplesstats.shapiro(control)
stats.zscore()Standardizes values or flags extreme valuesstats.zscore(df["enzyme_activity"])

Decision rule: Use a t-test for two numeric groups, chi-square or Fisher's exact test for categorical counts, correlation for two numeric variables, and regression when one numeric variable is being used to predict another.

Lesson 2

Practice Dataset: Enzyme Activity

This invented dataset simulates a simple biology question: does a treatment condition increase enzyme activity compared with a control condition?

sample_idconditiontemperature_cphenzyme_activitycell_viability
E01control377.211.296
E02control377.210.895
E03control377.111.594
E04control377.310.997
E05control377.211.096
E06control377.111.395
E07treatment397.214.193
E08treatment397.213.792
E09treatment397.114.591
E10treatment397.315.090
E11treatment397.213.992
E12treatment397.114.393
sample_id,condition,temperature_c,ph,enzyme_activity,cell_viability
E01,control,37,7.2,11.2,96
E02,control,37,7.2,10.8,95
E03,control,37,7.1,11.5,94
E04,control,37,7.3,10.9,97
E05,control,37,7.2,11.0,96
E06,control,37,7.1,11.3,95
E07,treatment,39,7.2,14.1,93
E08,treatment,39,7.2,13.7,92
E09,treatment,39,7.1,14.5,91
E10,treatment,39,7.3,15.0,90
E11,treatment,39,7.2,13.9,92
E12,treatment,39,7.1,14.3,93
Lesson 3

pandas: Read, Inspect, Filter, Summarize

A DataFrame is a table where each row is one observation and each column is one variable. For this dataset, each row is one enzyme sample.

Core Commands

import pandas as pd

df = pd.read_csv("enzyme_activity.csv")

print(df.head())
print(df.shape)
print(df.columns)
print(df["condition"].value_counts())

clean = df.dropna(subset=["condition", "enzyme_activity"])
summary = clean.groupby("condition")["enzyme_activity"].agg(["count", "mean", "std"])
print(summary)

The important line is groupby("condition"). It tells pandas to split the table into control rows and treatment rows before calculating count, mean, and standard deviation.

Lesson 4

NumPy: Numeric Thinking

NumPy is useful when the analysis becomes more mathematical. It treats columns as arrays of numbers, which makes calculations predictable and fast.

Mean, Difference, and Standard Deviation

import numpy as np

control = clean.loc[clean["condition"] == "control", "enzyme_activity"].to_numpy()
treatment = clean.loc[clean["condition"] == "treatment", "enzyme_activity"].to_numpy()

control_mean = np.mean(control)
treatment_mean = np.mean(treatment)
difference = treatment_mean - control_mean

print(control_mean)
print(treatment_mean)
print(difference)
print(np.std(control, ddof=1))
print(np.std(treatment, ddof=1))

Teacher note: Use ddof=1 for a sample standard deviation. Biology projects almost always measure samples, not every possible organism or molecule in the world.

Lesson 5

SciPy: Statistical Tests

The treatment mean is higher, but statistics asks whether the difference is large relative to the variation inside each group.

Welch Two-Sample t-Test

from scipy import stats

test = stats.ttest_ind(control, treatment, equal_var=False)
print(test.statistic)
print(test.pvalue)

Use equal_var=False because it does not assume the two groups have exactly the same variance. This is called Welch's t-test.

Interpretation template: The treatment group had a higher mean enzyme activity than the control group by X units. A Welch t-test gave p = Y, which is evidence that the groups differ in this sample. This does not prove the treatment is the only cause unless the experiment controlled other variables.
Practice

Exercises

Skill Check A

  1. How many rows and columns are in the dataset?
  2. What is the mean enzyme activity for each condition?
  3. What is the treatment minus control difference?

Skill Check B

  1. What is the mean cell viability for each condition?
  2. Why should the lower treatment viability be mentioned as a limitation?
  3. Write one figure caption for a bar chart of enzyme activity by condition.
Answer Key

Check Your Work

Skill Check A Answers

The dataset has 12 rows and 6 columns. The control mean enzyme activity is about 11.12. The treatment mean is 14.25. The treatment group is higher by about 3.13 activity units.

Statistical Test Answer

A Welch t-test gives t = -14.39 and p = 5.79e-07 when the comparison is control minus treatment. The negative sign only reflects the order of subtraction. The practical interpretation is that treatment samples show much higher enzyme activity in this dataset.

Skill Check B Answers

Mean cell viability is 95.5 for control and 91.83 for treatment. That matters because a treatment that increases enzyme activity might also reduce cell viability. A fair poster would say: "Treatment samples showed higher enzyme activity than controls, but treatment samples also had lower cell viability, so follow-up work should test whether the activity change is independent of stress or toxicity."