Warming up the neural circuits...
By the end of this chapter you will:
Most product, business, and telemetry data shows up as rows and columns. You can wrangle that with raw Python dictionaries, but it quickly becomes repetitive and error-prone.
Pandas gives a table-native for loading, selecting, aggregating, and inspecting data with less boilerplate.
Mental model: a DataFrame is a typed table with labeled axes. Good pandas work is mostly about managing schema intentionally.
import pandas as pd
df = pd.DataFrame(
{
"user_id": [101, 102, 103],
"city": ["Pune", "Delhi", "Pune"],
"spend": [1200.0, 980.0, 1575.0],
}
)
print(df.dtypes.to_dict())
# {'user_id': dtype('int64'), 'city': dtype('O'), 'spend': dtype('float64')}Schema awareness starts with dtypes and column naming consistency.
import pandas as pd
orders = pd.read_csv(
"orders.csv",
dtype={"order_id": "string", "customer_id": "string"},
parse_dates=["ordered_at"],
import pandas as pd
df = pd.DataFrame(
{"city": ["Pune", "Delhi", "Pune"], "spend": [1200, 980, 1575]},
index=["
print(df.head(2))
print(df.info())
print(df.describe(include="all"))head, info, and describe quickly expose missing values, cardinality patterns, and suspicious dtypes.
import pandas as pd
events = pd.DataFrame(
{
"event_id": [1, 2, 3],
"user_id": [101, 101, 102],
"event": ["login", "
import pandas as pd
df = pd.DataFrame({"city": ["Pune", "Delhi"], "spend": [1200, 980]})
out = df.assign(spend_bucket=lambda x
Treat pandas operations as schema transformations. Log what columns and dtypes changed after each major step.
| Step | Command | Why |
|---|---|---|
| Preview rows | df.head() | Detect obvious parsing failures quickly |
| Inspect dtypes | df.info() | Catch object-columns pretending to be numeric/date |
| Distribution scan | df.describe(include="all") | Spot skew, nulls, unusual cardinality |
| Validate key uniqueness | df[key].is_unique | Prevent bad joins and duplicates |
| Save cleaned snapshot | to_parquet / to_csv | Preserve reproducible pipeline checkpoints |
| Mistake | Why it hurts | Better move |
|---|---|---|
KeyError: 'revenue' | Column name mismatch, often from whitespace/casing | Normalize headers early (str.strip, lower-case policy) |
AttributeError: 'DataFrame' object has no attribute 'totl' | Typo via dot-access on column names | Prefer bracket access: df["total"] |
SettingWithCopyWarning: A value is trying to be set on a copy... | Chained indexing creates ambiguous mutation target | Use .loc[row_mask, "col"] = ... |
TypeError: Invalid comparison between dtype=datetime64[ns] and str | Date columns compared to raw strings | Parse dates and compare with pd.Timestamp |
ValueError: cannot reindex on an axis with duplicate labels | Duplicate index values during alignment | Validate uniqueness or reset index before reindex |
orders.csv with order_id, customer_id, ordered_atString ids and datetime64 ordered_atDataFrame with custom indexCorrect label and positional lookupsAny DataFrameCompact diagnostic outputDataFrame with id columnIndex-based lookup and plain-column export frameassign and return only selected columns in final output.spend + order_count dataDataFrame with engineered features and clean column orderBeginner:
"When should I use loc instead of iloc?"
Use
locwhen you want -based selection andilocwhen you want position-based selection.
"Why define dtypes during read_csv?"
It prevents incorrect type inference that can silently break downstream calculations and joins.
Senior:
"How do you make pandas pipelines maintainable in production?"
Enforce schema checks, separate stages, persist checkpoints, and test critical transformations with deterministic fixtures.
"How do you decide index strategy for analytics vs operational exports?"
Choose index for frequent internal access patterns, then normalize to plain columns at integration boundaries.
loc and iloc must be used intentionally to avoid selection bugs.Need controlled ingest -> read_csv with dtype + parse_dates
Need label lookup -> loc
Need positional lookup -> iloc
Need first-pass quality check -> head + info + describe
Need readable transforms -> assign + explicit final column setWhat is the practical difference between `loc` and `iloc`?
Explicit schema choices up front save hours of downstream debugging.
Use loc for labels, iloc for integer positions. Mixing them causes subtle bugs.
Set index when it simplifies your common lookup pattern. Reset index before export when consumers expect plain columns.
assign reduces side effects and makes each transformation explicit.