Selecting, filtering and cleaning
loc, iloc, boolean filters, missing values and type conversion — the routine work that makes up most of a data task.
Selecting columns and rows
df["name"] # one column -> Series
df[["name", "score"]] # several -> DataFrame
df.loc[df["score"] > 80, ["name", "score"]] # label-based, with a condition
df.iloc[0:3, 0:2] # position-based
df.at[0, "name"] # single scalar by label
df.iat[0, 0] # single scalar by position⚠️
Use
.loc/.iloc, not chained indexing like df[df.a > 1]["b"] = 0. Chained assignment writes to a temporary copy and does nothing — pandas warns about this for good reason.Filtering
df[df["score"] > 80]
df[(df["team"] == "A") & (df["score"] > 80)] # & and |, with parentheses
df[df["team"].isin(["A", "C"])]
df[df["name"].str.startswith("A")]
df[df["score"].between(70, 90)]
df[~df["name"].isna()]- Use
&,|,~— notand/or, which cannot handle arrays. - Wrap each comparison in parentheses; precedence will otherwise bite.
query()is often more readable:df.query("score > 80 and team == 'A'").
Cleaning
df.isna().sum()
df.dropna(subset=["score"]) # drop rows missing a key field
df["score"] = df["score"].fillna(df["score"].median())
df["team"] = df["team"].fillna("unknown")
df = df.drop_duplicates(subset=["name"], keep="first")
df["score"] = pd.to_numeric(df["score"], errors="coerce") # bad values -> NaN
df["date"] = pd.to_datetime(df["date"], errors="coerce")
df["name"] = df["name"].str.strip().str.title()💡
Prefer
errors="coerce" over letting a conversion raise: it turns unparsable values into NaN so you can see and count the damage instead of the whole job failing.Deriving new columns
df["pass"] = df["score"] >= 80
df["bucket"] = pd.cut(df["score"], bins=[0, 60, 80, 100], labels=["low", "mid", "high"])
df["initials"] = df["name"].str[0]
df.assign(score_pct=lambda d: d["score"] / d["score"].max()) # chainable
df.apply(lambda r: r["score"] * 2, axis=1) # slower; last resortFAQ
Why does SettingWithCopyWarning appear?
You are assigning into a slice that may be a copy. Fix the root cause: select with
.loc in one step, or call .copy() when you truly intend a standalone frame.How do I rename or reorder columns?
df.rename(columns={...}) and df.reindex(columns=[...]) (or df[["a","b"]]) respectively.Related
Series and DataFrame Grouping, joining and reshaping
Last refreshed 2026-09-18.