NumPy and pandas basics
NumPy gives you arrays that do maths all at once; pandas gives you tables with named columns. Compare three tiny embeddings with cosine similarity, then summarise an eval run with groupby.
Two libraries carry most of the numeric work in AI projects. NumPy provides the ndarray: a block of numbers of one type, with operations that apply to every element at once. a + b adds two arrays element by element; np.dot(a, b) multiplies pairs and sums them; np.linalg.norm(a) is a vector’s length. No for loops, and the work happens in compiled code.
pandas sits on top of NumPy and adds the DataFrame: a table with named columns and a row index. You build one from a dict of lists, select a column with df["score"], keep rows with a boolean condition, and summarise groups with groupby. If you have used a spreadsheet, you already have the mental model.
Both are installed with pip install numpy pandas and imported as np and pd by convention. The program below was run in a fresh virtual environment and the output is copied as printed, with values rounded for display.
Press Run for the NumPy part: three 3-number “embeddings” and their cosine similarity. Then switch Try it to the pandas part, where a small eval run becomes a DataFrame.
# Part 1: compare tiny "embeddings" with NumPy.
import numpy as np
import pandas as pd
dosa = np.array([0.9, 0.1, 0.3])
idli = np.array([0.8, 0.2, 0.4])
laptop = np.array([0.1, 0.9, 0.2])
def cosine(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
print("dosa + idli =", dosa + idli)
print("dosa . idli =", round(np.dot(dosa, idli), 3))
print("cosine(dosa, idli) =", round(cosine(dosa, idli), 3))
print("cosine(dosa, laptop) =", round(cosine(dosa, laptop), 3))
# Part 2: eval results in a pandas DataFrame.
results = pd.DataFrame({
"agent": ["weather", "weather", "weather", "booking", "booking"],
"case": ["c1", "c2", "c3", "c1", "c2"],
"score": [1.0, 0.5, 1.0, 0.0, 1.0],
})
print(results)
print("overall:", results["score"].mean())
print(results.groupby("agent")["score"].mean().round(2))
failed = results[results["score"] < 0.5]
print("failed cases:", list(failed["case"]))Press Play to run the program line by line, or step with ← →.
Variables
Nothing defined yet.
Output
Nothing printed yet.
What to notice
- Arrays do maths without loops.
dosa + idligives a new array. The shapes must match; NumPy raises an error otherwise, which catches a lot of bugs early. - Cosine similarity is three calls.
np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b)). Close to 1 means the vectors point the same way; near 0 means unrelated.dosaandidliscore 0.984,dosaandlaptop0.271. - Floats are approximate. The raw dot product is
0.8600000000000001. Round when you display, compare with a tolerance, never with==. - A dict of lists is a DataFrame. Keys become column names. The index
0..4on the left is added by pandas. - groupby is split-apply-combine. Split the rows by
agent, applymeantoscore, combine the results into one Series. Selecting the column before the aggregation,groupby("agent")["score"], is the efficient way. - Boolean filtering keeps rows.
results["score"] < 0.5is a column of True/False;results[...]with it returns only the True rows.
Why this matters for AI work
An embedding model turns text into a vector with hundreds of numbers, and “similar meaning” becomes “small angle between vectors”, which is cosine similarity on NumPy arrays. Embeddings shows the picture; the three lines in cosine() are the maths. On the evaluation side, every eval tool gives you rows of (agent, case, score). Load them into a DataFrame, groupby by agent or by version, filter the failures, and you have a report instead of a wall of JSON.