pandas Cheatsheet

Useful Methods

Use this pandas reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Inspection and Summary

df.head(5)              # first N rows
df.tail(5)              # last N rows
df.sample(10)           # random N rows
df.sample(frac=0.1, random_state=42)

df.info()               # dtypes, non-null counts, memory
df.describe()           # stat summary (numeric by default)
df.describe(include="all")

df.shape                # (rows, cols)
df.dtypes               # dtype per column
df.memory_usage(deep=True)
df.memory_usage(deep=True).sum()   # total bytes

Type Utilities

pd.api.types.is_numeric_dtype(df["col"])
pd.api.types.is_string_dtype(df["col"])
pd.api.types.is_datetime64_any_dtype(df["col"])
isinstance(df["col"].dtype, pd.CategoricalDtype)   # is_categorical_dtype deprecated ≥2.1

df.select_dtypes(include="number")
df.select_dtypes(exclude=["object", "category"])

Deduplication

df.duplicated()                        # bool Series: True = duplicate row
df.duplicated(subset=["a", "b"])       # duplicate on specific columns
df.duplicated(keep="last")             # mark earlier copies as duplicate
df.duplicated(keep=False)              # mark ALL copies

df.drop_duplicates()                   # keep first occurrence
df.drop_duplicates(subset=["a", "b"])
df.drop_duplicates(keep="last")
df.drop_duplicates(keep=False)         # drop all duplicated rows entirely

Sorting

df.sort_values("col")
df.sort_values(["col1", "col2"], ascending=[True, False])
df.sort_values("col", na_position="first")
df.sort_values("text", key=lambda s: s.str.lower())   # case-insensitive sort
df.sort_index()
df.sort_index(level="month")                          # sort by a MultiIndex level

s.sort_values()
s.rank()                              # rank (average by default)
s.rank(method="min")                  # "average"|"min"|"max"|"first"|"dense"
s.rank(pct=True)                      # fractional rank
s.rank(ascending=False)               # rank descending

pipe() — Chainable Custom Functions

def add_tax(df, rate=0.08):
    df["tax"] = df["price"] * rate
    return df

result = (
    df
    .pipe(add_tax, rate=0.1)
    .pipe(lambda d: d[d["tax"] > 1])
    .reset_index(drop=True)
)

assign() — Chainable Column Creation

df = (
    df
    .assign(total=df["price"] * df["qty"])
    .assign(discount=lambda d: d["total"] * 0.05)
    .assign(final=lambda d: d["total"] - d["discount"])
)

eval() and query() — Expression Strings

df.eval("a + b * c")                          # returns Series
df.eval("total = price * qty", inplace=True)   # adds column
df.query("score > 50 and status == 'active'")
df.query("city in ['NYC', 'LA']")
threshold = 30
df.query("age > @threshold")                   # @ references local variable

String Methods (str Accessor)

s.str.lower() / s.str.upper() / s.str.title()
s.str.strip() / s.str.lstrip() / s.str.rstrip()
s.str.replace("old", "new")
s.str.replace(r"\s+", "_", regex=True)
s.str.contains("pattern", na=False, case=False)
s.str.startswith("prefix")
s.str.endswith("suffix")
s.str.split(",")                  # → list per cell
s.str.split(",", expand=True)     # → DataFrame of splits
s.str.get(0)                      # first element after split
s.str.join("-")                   # join list elements
s.str.len()                       # length of each string
s.str.count("a")                  # occurrences of pattern
s.str.extract(r"(\d+)")           # first capture group → DataFrame
s.str.extractall(r"(\d+)")        # all matches → multi-row result
s.str.findall(r"\d+")             # list of all matches
s.str.zfill(5)                    # zero-pad to width
s.str.pad(10, side="left")
s.str.center(20, fillchar="-")
s.str.slice(0, 5)                 # s.str[0:5]
s.str.cat(sep=", ")               # concatenate all strings in Series
s.str.get_dummies(sep="|")        # one-hot from delimited strings

map(), apply(), applymap() / map() on DataFrame

# Series.map — element-wise, dict or callable
s.map({"a": 1, "b": 2})
s.map(str.upper)

# Series.apply — like map but callable only, richer output support
s.apply(lambda x: x**2)

# DataFrame.apply — column-wise or row-wise
df.apply(np.sum)              # per column
df.apply(np.sum, axis=1)      # per row

# DataFrame element-wise (pandas ≥ 2.1: map; older: applymap)
df.map(lambda x: x**2)       # new name
df.applymap(lambda x: x**2)  # old name (deprecated 2.1)

Utility Functions

pd.isna(val)           # True for NaN / None / NaT / pd.NA
pd.notna(val)

pd.to_numeric(s, errors="coerce")
pd.to_datetime(s, errors="coerce")
pd.to_timedelta(s, unit="s")

pd.cut(s, bins=5)                             # equal-width bins
pd.cut(s, bins=[0, 18, 65, 120], labels=["child", "adult", "senior"])
pd.qcut(s, q=4)                               # equal-frequency bins
pd.qcut(s, q=4, labels=["Q1","Q2","Q3","Q4"])

pd.get_dummies(s)
pd.factorize(s)                               # integer codes + unique array

pd.interval_range(start=0, end=10, periods=5)
pd.arrays.IntervalArray.from_breaks([0, 1, 3, 6])

Iteration (prefer vectorized, but when needed)

# Iterate rows — slow
for idx, row in df.iterrows():        # each row as Series
    print(idx, row["col"])

for row in df.itertuples(index=True, name="Row"):  # faster, namedtuple
    print(row.col)

# Iterate columns
for col_name, col_series in df.items():
    print(col_name, col_series.dtype)

Avoid iterrows() for numeric operations — it's orders of magnitude slower than vectorized methods.

reindex() and align()

# Conform to a new set of labels (NaN for missing)
df.reindex([0, 1, 2, 99])
df.reindex(columns=["a", "b", "c", "new_col"])
df.reindex(new_index, fill_value=0)
df.reindex(new_index, method="ffill")  # fill gaps

# align() — conform two objects to the same index simultaneously
left, right = df1.align(df2, join="outer", fill_value=0)

clip(), round(), abs()

df["val"].clip(lower=0, upper=100)
df.clip(lower=-3, upper=3)     # all columns

df["price"].round(2)
df.round({"price": 2, "qty": 0})

df["amount"].abs()
df.abs()

Displaying Options

pd.set_option("display.max_rows", 100)
pd.set_option("display.max_columns", 50)
pd.set_option("display.float_format", "{:.2f}".format)
pd.set_option("display.width", 120)

pd.reset_option("all")       # restore defaults

# Context manager for temporary settings
with pd.option_context("display.max_rows", 200):
    print(df)

Styling (Jupyter)

df.style.highlight_max(color="lightgreen")
df.style.highlight_min(color="salmon")
df.style.background_gradient(cmap="Blues")
df.style.format({"price": "${:.2f}", "pct": "{:.1%}"})
df.style.bar(subset=["score"], color="#aaffaa")
df.style.hide(axis="index")