Getting Started with pandas

Learn to work with tables of data in Python using pandas. Build Series and DataFrames, load a CSV file and check what you loaded, and pick out exactly the rows and columns you need by label with loc and by position with iloc. Filter rows with conditions, add and transform columns, sort and rank values, and summarize data with descriptive statistics, value counts and correlation. Examples follow pandas 3.

IntermediateLesson 2 of 8 in Data Analysis with Python Course

What you will learn

  1. Describe how pandas stores labeled one- and two-dimensional data, build Series and DataFrames from Python data, and manage their row and column labels.
    • Create a Series and use its index
      Build a Series from a list or dictionary, read its values, index, dtype and name, and predict how labels behave in arithmetic and lookups.
    • Build a DataFrame and read its structure
      Create a DataFrame from Python data, read its shape, columns, index and dtypes, select a column as a Series, and use the axis argument correctly.
    • Set, reset, rename and drop labels
      Choose a meaningful row index, move it back into a column, rename and drop rows or columns, and keep the results by reassigning them.
  2. Read a CSV file into a DataFrame with the right options, inspect the result systematically, and convert columns to the types the analysis needs.
    • Read a CSV file with read_csv
      Load a comma-separated file with pd.read_csv, understand how pandas infers column types, and use the options for separators, decimals, headers, missing values and identifiers.
    • Inspect a new DataFrame
      Check a freshly loaded table with head, info, shape, dtypes, missing-value counts and unique counts before analyzing it.
    • Convert columns to the right types
      Change a column's dtype with astype, pd.to_numeric and pd.to_datetime, and keep the converted column by assigning it back.
  3. Pick out exactly the rows, columns and single values you need with loc (labels) and iloc (positions), and predict the shape and type of each result.
    • Select rows and columns by label with loc
      Use df.loc[rows, columns] with single labels, lists, inclusive slices and boolean masks, and recognize when a label does not exist.
    • Select by position with iloc and choose the right indexer
      Use df.iloc[rows, columns] with integer positions, exclusive slices and negative positions, read single values with at and iat, and decide between label and position selection.
  4. Keep only the rows that meet one or more conditions, using boolean masks, the helper methods for common tests and query, and change values in selected rows safely.
    • Filter with boolean masks
      Build a True/False mask from a comparison, combine conditions with &, | and ~, count matches, and understand how missing values behave in comparisons.
    • Use helper methods and query for common filters
      Filter with isin, between, isna/notna and str.contains, and write the same conditions as a readable query string.
    • Change values in selected rows safely
      Update values in the rows that match a condition with a single loc assignment, and avoid chained assignment, which does not change the original table in pandas 3.
  5. Create new columns from existing ones with vectorized arithmetic and assign, and recode or transform values with np.where, map, apply and replace.
    • Compute new columns from existing ones
      Add or overwrite a column with vectorized arithmetic, use assign to build columns in a chain, and predict how missing values and index alignment affect the result.
    • Recode and transform values with np.where, map and apply
      Turn conditions into labels with np.where, translate values with map and replace, apply your own functions with apply, and prefer vectorized forms where they exist.
  6. Order rows by one or more columns, rank values with a suitable tie rule, compute descriptive statistics for numeric and text columns, and count values and relationships.
    • Sort rows by values or by index
      Sort a DataFrame by one or several columns in either direction, control where missing values and ties go, and find the top or bottom rows.
    • Rank values and handle ties
      Give each value its rank with rank, choose a tie method that fits the purpose, and express ranks as percentiles.
    • Summarize columns with descriptive statistics
      Compute counts, totals, centers, spread and quartiles with pandas methods and describe, interpret them, and handle missing values and text columns correctly.
    • Count values and measure relationships
      Count how often each value occurs, list distinct values, express counts as proportions, and measure the linear relationship between two numeric columns with correlation.

Getting Started with pandas study guide

6 chapters

1

Understand Series and DataFrames

Labels turn a sequence of numbers into data you can identify and combine. Build a Series for one variable and a DataFrame for several variables, then read their dimensions and types. You will see why matching labels matters in arithmetic, how a column differs from a one-column table, and how choosing, resetting or renaming an index changes later lookups. These structures support every selection and calculation that follows.

1.1 Create a Series and use its index

A Series keeps a sequence of values together with labels. Those labels give the values meaning: a rain reading belongs to a day, and a population belongs to a city. Import pandas and NumPy using their usual short names.

import pandas as pd
import numpy as np
rain = pd.Series([4.5, 3.0, 6.2],
                 index=["Mon", "Tue", "Wed"], name="rain_mm")
Read values and labels

The values are 4.5, 3.0 and 6.2; the index is Mon, Tue and Wed. Without index=, pandas supplies labels 0, 1 and 2. A dictionary supplies both at once: pd.Series({"Lima": 10, "Oslo": 5, "Pune": 7}) takes its labels from the keys, in dictionary order.

Attributes describe the Series without parentheses: rain.index holds the labels, rain.dtype is float64, rain.name is "rain_mm" and rain.size is 3. Use rain.to_numpy() when a NumPy array is needed. The older .values returns different kinds of array for different dtypes; text data can give a pandas array.

A dtype tells pandas what kind of values it stores. Common types are int64 for whole numbers, float64 for decimals, bool for True/False, str for text and datetime64 for dates and times. pandas 3 infers text as str; older examples often display object.

Work on the whole Series

For s = pd.Series([10, 20, 30], index=["a", "b", "c"]), s * 2 produces values 20, 40 and 60. s > 15 produces False, True and True. Both keep the labels. These operations are vectorized: one expression works on the whole Series without a Python loop.

Look up a label with s["b"], which gives 20. Look up a position with s.iloc[0], which gives 10. The expression "b" in s checks the index; 20 in s is False. Even an integer in square brackets is a label: with index [2, 0, 1], s[0] means label 0, not the first entry. With text labels, s[0] raises KeyError in pandas 3.

Match labels in arithmetic
a = pd.Series([1, 2, 3], index=["x", "y", "z"])
b = pd.Series([10, 20, 30], index=["y", "z", "w"])
a + b

The shared label y combines 2 and 10 to give 12.0; z combines 3 and 20 to give 23.0. Labels w and x appear in only one input, so they receive NaN. The result includes all four labels. Adding by visual row position would incorrectly give 11, 22 and 33.

Use a.add(b, fill_value=0) when an absent value should count as zero. Its results are w 30.0, x 1.0, y 12.0 and z 23.0. Related methods include sub, mul and div.

Recognize missing values

A missing float or str value uses NaN; a missing datetime uses NaT; a missing nullable integer uses <NA>. pd.Series([1, None, 3]) becomes float64, displaying 1.0, NaN and 3.0, because ordinary int64 cannot hold NaN.

Key Takeaways

  • A Series combines one sequence of values with an index, a dtype and an optional name.
  • Use a label for lookup and iloc for a position; membership tests check labels.
  • Vectorized arithmetic acts on every value while keeping the index.
  • Two Series align by label; unmatched labels get missing results unless a fill value is supplied.
  • Missing-value markers depend on dtype: NaN, NaT or <NA>.

1.2 Build a DataFrame and read its structure

A DataFrame is a two-dimensional table. Each row records one observation, such as an order; each column holds one variable, such as a quantity. Columns can have different dtypes, but they share the same row index.

Build a table from Python data
df = pd.DataFrame({
    "product": ["Notebook", "Desk lamp", "Pen set", "Mug"],
    "quantity": [3, 1, 2, 4],
    "unit_price": [2.50, 18.00, 4.75, 6.00]
})

Each dictionary key becomes a column name; each list supplies that column's values. The lists must have equal lengths so that each row has a place in every column. Here the index labels are 0 through 3. Lists of different lengths raise a ValueError.

A list of dictionaries instead supplies one dictionary per row. pd.DataFrame([{"a": 1, "b": 2}, {"a": 3, "c": 4}]) creates columns a, b and c. The missing b in the second row and missing c in the first become NaN, so those columns use float64. A two-dimensional NumPy array can also supply values, with columns=[...] naming the columns.

Read the table's dimensions

df.shape is (4, 3): four rows and three columns, in that order. len(df) is 4, while df.size is 12 because it counts cells. df.index holds row labels, df.columns holds column labels and df.dtypes gives one dtype per column. These are attributes: df.shape() tries to call a tuple and raises TypeError. df.T swaps rows and columns.

Keep a Series or keep a table
SelectionResult
df["quantity"]A Series
df[["quantity"]]A one-column DataFrame
df[["product", "unit_price"]]A DataFrame with two columns in that order

The inner list requests a collection of columns. Without it, df["product", "unit_price"] supplies one tuple key, which does not match either ordinary column name and raises KeyError.

Square brackets also work when names contain spaces or clash with methods. Dot notation such as df.quantity only works for suitable names. A column called size needs df["size"], because df.size means the table's cell count. Create columns with square brackets too: df["total"] = 5 adds a column, while df.total = 5 does not.

Choose an axis

For numbers = pd.DataFrame({"a": [1, 2], "b": [3, 4]}), numbers.sum() adds down the rows, giving a 3 and b 7. This is axis=0, also called "index". numbers.sum(axis=1) adds across each row, giving 4 and 6; this axis is also called "columns". Name the result you need first: one total per column or one total per row.

Taking one row creates a Series whose labels are the column names. That Series needs one dtype able to hold every cell in the row. A row mixing integers and floats becomes float64; a row mixing text and numbers becomes object. The original columns still retain their separate types.

Key Takeaways

  • A DataFrame has a shared row index and one dtype per column.
  • Equal-length lists supply columns; a list of dictionaries supplies rows.
  • shape counts rows and columns; size counts cells.
  • A single column name returns a Series; a list of names returns a DataFrame.
  • axis=0 reduces down rows; axis=1 reduces across columns.
  • Use square brackets for column names that clash with attributes or methods.

1.3 Set, reset, rename and drop labels

Row labels can carry meaning, such as an order number, or simply label the current rows. Choosing a useful index makes lookups and later results easier to interpret. Changing labels returns a new table, so keep the result with an assignment.

Move an ID into the index
orders = pd.DataFrame({
    "order_id": [1001, 1002, 1003],
    "product": ["Notebook", "Desk lamp", "Pen set"],
    "unit_price": [2.50, 18.00, 4.75]
})
orders_by_id = orders.set_index("order_id")

The original table has a default RangeIndex: 0, 1 and 2. The new table has labels 1001, 1002 and 1003. order_id has moved out of the columns into the index. orders_by_id.loc[1002] now identifies the Desk lamp row by its ID.

Calling orders.set_index("order_id") without saving its result leaves orders unchanged. Reassignment, such as orders = orders.set_index("order_id"), keeps the new structure. In pandas 3.1, inplace= is deprecated for these label-changing methods and for sorting; use assignment.

Move labels back into a column

orders_by_id.reset_index() restores order_id as an ordinary column and supplies a new RangeIndex. An unnamed index becomes a column called index. This preserves the old row identity.

reset_index(drop=True) discards the old labels. For an index [10, 20, 30], plain reset_index() keeps those numbers in an index column; reset_index(drop=True) loses them and uses 0, 1 and 2. After filtering or sorting, choose whether the old labels are useful before discarding them. Renumbering the index does not change the data values or undo a sort.

Rename or remove labels
renamed = orders.rename(columns={"unit_price": "price"})
short = orders.drop(columns=["product"])
remaining = orders.drop(index=[0, 1])

rename maps old labels to new ones and keeps names not listed. By default a misspelled old name is ignored, so inspect .columns if a rename seems to have done nothing. To replace every column name, assign a full list to orders.columns; its length must match the column count.

drop(columns=...) removes columns; drop(index=...) removes rows by label. A label that is absent raises KeyError. After sorting, label 0 may no longer be the first row: dropping it still removes the row labeled 0.

Select a list to choose column order: orders = orders[["order_id", "unit_price", "product"]]. Columns absent from that list are removed from the result.

Check that an ID really identifies one row

Index labels can repeat. Check orders_by_id.index.is_unique before treating them as unique IDs. If label 1002 occurs twice, .loc[1002] returns both rows as a DataFrame. With unique labels, the same single-label lookup returns a Series.

A meaningful index also improves summaries. In a weather table indexed by day, weather["temp_c"].idxmax() reports a day such as "Thu"; with a default index it reports a row number.

Key Takeaways

  • set_index moves a column into row labels; reset_index moves labels back into a column.
  • reset_index(drop=True) discards old labels.
  • Keep label changes by assigning the returned table.
  • rename changes named labels; drop removes rows or columns by label.
  • An index can contain duplicates; check uniqueness before using it as an ID.
2

Load a CSV file and check what you loaded

A loaded table needs a check before its numbers can support an analysis. Match CSV options to the file’s delimiter, header and value conventions, then inspect the result for the expected rows, names and types. Trace missing entries and repeated IDs, and convert numeric text or date text when needed. Small import choices matter: a lost leading zero or an unparsed date can change what later code means.

2.1 Read a CSV file with read_csv

A CSV stores a table as text: records occupy lines and a delimiter separates fields. The first line often contains column names. Loading the file correctly means identifying both its layout and the meaning of its values.

Load the orders table
orders = pd.read_csv("orders.csv")

A relative path is resolved from Python's current working directory. A wrong location raises FileNotFoundError. An absolute path or a URL can also be passed to read_csv.

The examples use this file. The final row has an empty quantity field.

order_id,date,product,category,quantity,unit_price
1001,2026-03-02,Notebook,Stationery,3,2.50
1002,2026-03-02,Desk lamp,Home,1,18.00
1003,2026-03-03,Pen set,Stationery,2,4.75
1004,2026-03-04,Mug,Home,4,6.00
1005,2026-03-04,Backpack,Bags,1,35.00
1006,2026-03-05,Notebook,Stationery,,2.50

With defaults, the result has shape (6, 6) and index labels 0 through 5. pandas infers types: order_id is int64, unit_price is float64, and quantity also becomes float64 because its blank becomes NaN. The other columns, including date, are str. A date-looking string is still text until parsed.

Match the file's layout
File featureReading option
Fields separated by semicolonssep=";"
Decimal commasdecimal=","
No header lineheader=None, names=["id", "product"]
Two extra lines before the headerskiprows=2
Only selected fields neededusecols=["product", "quantity"]
A short previewnrows=100

For a file whose lines are a;b, 1,5;2 and 3,0;4, use pd.read_csv("file.csv", sep=";", decimal=","). Column a then contains 1.5 and 3.0. Using the default comma separator produces one column named a;b, a sign to check the delimiter.

index_col="order_id" makes that column the row index during loading. thousands="," reads a field such as "1,200" as 1200; in a comma-separated file the field needs CSV quoting so that its internal comma is not another delimiter.

Preserve meaning while inferring types

Codes such as "001" are identifiers, not amounts. dtype={"id": str} preserves their leading zeros. If pandas first converts them to 1, converting that number back to text cannot recover how many zeros the file contained.

Empty fields and common markers such as NA, N/A, NULL, NaN and None are missing by default. Add a file's special marker with na_values=["-"]. These are loading rules, so check the file's conventions when a code looks like a missing marker.

Use parse_dates=["date"] to read the example dates as datetimes. In pandas 3 these dates use microsecond resolution, datetime64[us]. UTF-8 is the default text encoding. A UnicodeDecodeError calls for checking the file's encoding and supplying the matching option, such as encoding="latin-1".

Key Takeaways

  • read_csv returns a DataFrame and infers column types.
  • Match sep, decimal and header options to the file layout.
  • Preserve leading zeros in identifiers with a text dtype during loading.
  • Blank fields and common missing markers become missing values; na_values adds markers.
  • Dates need parsing, using parse_dates during loading or conversion later.
  • A relative path is resolved from the current working directory.

2.2 Inspect a new DataFrame

A successful read means pandas could parse the file. It does not establish that the columns, types and missing values match what the table is meant to represent. Inspect the new DataFrame before calculating from it.

Check visible rows and dimensions
orders.head(3)
orders.tail()
orders.shape
orders.columns.tolist()

head() shows five rows by default; head(3) shows three. tail() checks the end, where an export may contain different records. sample(3, random_state=0) gives a repeatable random sample of three rows. In a notebook, a cell's final expression displays automatically; use print elsewhere.

The orders file should contain six rows and six columns. A preview should show named columns and the first order as data. If the first record appears among the column names, the file probably lacks a header and needs header=None. If everything occupies one wide column, check sep.

Column names match exactly, including case and spaces. orders["Product"] fails when the name is product. Inspecting the list makes trailing spaces easier to spot. orders.columns = orders.columns.str.strip() removes spaces at the ends of header names.

Read the structure with info

orders.info() prints the index range, each column's name, count of present values, dtype and memory use. For the six-row example, quantity has five non-null values; the other columns each have six. The dtypes are two float columns, one integer column and three str columns. orders.dtypes gives a compact type list.

A numeric-looking column with dtype str deserves inspection: a token such as "unknown", a unit such as "12 kg" or an unhandled thousands separator can block numeric inference. Dates also remain text unless parsed. Decide the needed type from the column's meaning, not only its appearance in a preview.

Count gaps and repeated values
orders.isna().sum()
orders.isna().any(axis=1).sum()
orders.nunique()

isna() makes a boolean table: True marks a missing cell. Summing down each column counts those cells. Quantity has one missing value and every other column has zero. To count affected rows, .any(axis=1) first checks whether each row has any gap, then .sum() counts those rows. Adding all column counts instead could count one row several times.

nunique() counts distinct present values: the orders have six IDs, four dates, five products, three categories, four quantities and five prices. Compare the ID count with the row count to check uniqueness, along with its missing count. orders.duplicated(subset="product") marks the second Notebook row, label 5, as repeated. A repeated product is legitimate here; a repeated order ID would need investigation.

Read a quick numeric overview

orders.describe() reports count, mean, standard deviation, minimum, quartiles and maximum for numeric columns. Quantity's count is five, so its mean summarizes five recorded quantities. Check plausible ranges and units as well as types: a column can be numeric and still contain an input error. Keep the observed row count, column count, types, missing counts and ID check together when reviewing a new load.

Key Takeaways

  • Use previews, dimensions, exact column names and dtypes together after loading.
  • info() prints non-null counts and types; it does not return a summary table.
  • isna().sum() counts missing cells per column; .any(axis=1).sum() counts affected rows.
  • Check both missing IDs and the number of distinct IDs.
  • describe() counts show how many recorded values support a numeric summary.

2.3 Convert columns to the right types

A column's dtype determines which operations make sense. A text column containing "12" still stores text; it cannot be averaged as a numeric column. Convert deliberately and assign the result back to the table.

Choose strict conversion or coercion

astype converts a Series to a named type, such as int, float, str or "Int64". It fails when a value cannot be represented in the requested type.

raw = pd.Series(["12", "7", "n/a", "3.5"])
numeric = pd.to_numeric(raw, errors="coerce")

raw.astype(float) raises ValueError at "n/a". With errors="coerce", the output values are 12.0, 7.0, NaN and 3.5. The failed token becomes missing instead of stopping the conversion. Compare raw.isna().sum() with numeric.isna().sum(): zero missing values became one, identifying a value that needs checking.

Coercion is a conversion policy, not evidence that every new gap is harmless. Use the before-and-after counts to find losses. Store the conversion in a new variable or column when the raw text is useful for tracing a failed value.

Keep missing whole numbers

The orders quantity column contains whole numbers plus one NaN, so it is float64. Plain astype(int) fails because NaN has no ordinary integer representation.

orders["quantity"] = orders["quantity"].astype("Int64")

The capital I matters: nullable Int64 keeps the gap as <NA> while storing the known values as whole numbers. This choice fits counts with missing entries. It does not make a genuinely fractional quantity into a valid whole-number count.

Text thousands separators also need handling. pd.Series(["1,200", "950"]).str.replace(",", "").astype(int) yields 1200 and 950. When the file itself uses that convention, thousands="," can handle it during reading.

Convert date text
orders["date"] = pd.to_datetime(orders["date"])
orders["date"].dt.day_name()

The conversion enables .dt.year, .dt.month, .dt.day and .dt.day_name(). For the six order dates, the day names are Monday, Monday, Tuesday, Wednesday, Wednesday and Thursday. Running pd.to_datetime(orders["date"]) alone produces a converted Series but leaves the original column as text. The assignment is what keeps it.

Store repeated categories

orders["category"].astype("category") stores repeated labels through a set of allowed categories. On large tables this usually saves memory. Assign the result to keep it, just as for other conversions.

Category dtype changes some operations. Its categories are unordered by default, so min() and max() raise TypeError. A category column's value_counts() also lists known categories absent from a filtered selection with count zero. Choosing category dtype is useful for repeated labels, but it is a change in behavior as well as storage.

Key Takeaways

  • astype fails on invalid conversions; to_numeric(errors="coerce") turns invalid tokens into missing values.
  • Compare missing counts before and after coercion.
  • Nullable Int64 stores whole numbers with missing entries.
  • Convert dates with to_datetime and read date parts through .dt.
  • Keep conversions by assigning their results.
  • Unordered category dtype saves repeated labels efficiently but changes some summaries.
3

Select data by label and by position

A row can be identified by its label or found by its current position. Learn to make that choice explicit with loc and iloc, select the needed columns at the same time, and predict whether a selection returns a value, a Series or a DataFrame. Slice endpoints and retained labels explain many off-by-one errors. The distinction becomes especially useful after a table has been sorted or filtered.

3.1 Select rows and columns by label with loc

Labels let you ask for the row or column by its meaning. With loc, an order number identifies a row even if the table has been sorted. The selection has a row part followed by a column part: df.loc[rows, columns].

Start from a meaningful index

The orders file has six rows with IDs 1001 through 1006. Create orders_by_id = orders.set_index("order_id"). Its columns, in order, are date, product, category, quantity and unit_price. The row labels are order numbers, not positions 0 through 5.

orders_by_id.loc[1003]
orders_by_id.loc[1004, "product"]

The first expression returns order 1003 as a Series: date "2026-03-03", product "Pen set", category "Stationery", quantity 2.0 and price 4.75. The Series is named 1003. The second returns one cell, "Mug".

A missing label raises KeyError. orders_by_id.loc[0] fails: having a first row at position 0 does not create a label 0.

Select collections of labels
orders_by_id.loc[[1001, 1005], ["product", "unit_price"]]

Lists select labels in the order requested. This gives two rows and two columns: Notebook at 2.5, then Backpack at 35.0. A list preserves a table-shaped result even when it contains one label: .loc[[1003]] is a one-row DataFrame.

RequestForm
One value.loc[1004, "product"]
One full row.loc[1004]
A one-row table.loc[[1004]]
All rows, one column.loc[:, "unit_price"]

A colon alone means all labels along that axis. Leaving out the column selector also requests all columns.

Include both ends of a label slice
orders_by_id.loc[1002:1004, "product":"quantity"]

On this ordered index, the rows are 1002, 1003 and 1004. The column slice includes product, category and quantity. Both the row stop label and the column stop label are included, so the shape is (3, 3). Applying Python's usual exclusive-stop rule here would omit an intended row and column.

Labels survive sorting

A default index can hide the distinction between label and position. Suppose sorting scores gives row labels 3, 0, 2, 1, 4. .loc[0] still selects label 0, now the second displayed row. .iloc[0] selects the top displayed row, label 3. Sorting moves a row with its label; it does not silently renumber the index.

Combine a condition with column selection

The row selector can be a boolean Series:

orders.loc[orders["unit_price"] > 5, ["product", "unit_price"]]

This keeps Desk lamp at 18.0, Mug at 6.0 and Backpack at 35.0, and returns only the two requested columns. The mask decides which rows qualify; the column list decides what to show. The same two-axis form can target cells for an update by putting the selection on the left side of an assignment.

Key Takeaways

  • loc selects row labels and column names.
  • Lists request labels in their listed order and preserve a DataFrame on that axis.
  • Label slices include the stop label; a colon selects all labels.
  • Missing requested labels raise KeyError.
  • Sorting moves labels with rows, so label 0 can differ from position 0.
  • A boolean row mask and column names can share one loc call.

3.2 Select by position with iloc and choose the right indexer

Use iloc when a request concerns where a row or column sits: the first three rows, the last column or a particular displayed cell. Its selectors are integer positions, independent of the index labels.

Count from zero

orders.iloc[0] selects the first row and orders.iloc[-1] the last. A negative position counts backward from the end. Two positions select a cell: orders.iloc[2, 2] is "Pen set" in the original orders table, where product is column position 2.

The indexed table orders_by_id has columns date, product, category, quantity and unit_price. Moving order_id into the index changed its column positions, so product is now position 1. Position-based code depends on this layout.

Stop before the slice endpoint
orders_by_id.iloc[1:3, 0:2]

The selected row positions are 1 and 2, containing orders 1002 and 1003. The column positions are 0 and 1, date and product. Position 3 and column 2 are excluded, giving shape (2, 2). An empty start means the beginning; an empty stop means the end.

Lists request particular positions, including a mixture of positive and negative ones. orders.iloc[[0, -1], [2, 5]] selects product and unit_price for the first and last orders. Both happen to be Notebook at 2.5.

Predict the result's shape
SelectionResult
orders.iloc[0, 2]One value
orders.iloc[0]A Series for one row
orders.iloc[:, 2]A Series for one column
orders.iloc[[0]]A one-row DataFrame
orders.iloc[0:1, 2:3]A one-row, one-column DataFrame

A scalar selects one item along an axis and removes that dimension. A slice or list keeps that axis, even if it selects just one item. This matters when the next operation expects a table instead of a Series.

Handle the end of a table

The six-row orders table has valid nonnegative row positions 0 through 5. orders.iloc[10] raises IndexError. A slice can extend beyond the table: orders.iloc[4:100] simply returns the last two rows. A single missing position is an invalid item request, while a slice describes a range that is clipped at the available rows.

Choose labels or positions deliberately

For a single cell, at uses labels and iat uses positions. orders.at[2, "product"] and orders.iat[2, 2] both give "Pen set" before the rows are reordered.

Choose loc when you know an ID or a column's meaning. Choose iloc when the location itself matters. To combine first rows with a column name, orders.columns.get_loc("quantity") returns its position, 4, allowing orders.iloc[0:3, 4].

Bare square brackets can switch roles: orders["product"] selects a column, but orders[2:4] slices row positions 2 and 3. Explicit loc and iloc make that choice easier to read.

Key Takeaways

  • iloc uses zero-based integer positions; negative positions count from the end.
  • Position slices exclude their stop and can extend beyond the available rows.
  • A single out-of-range position raises IndexError.
  • Scalar selectors remove a dimension; lists and slices keep it.
  • at selects one cell by label and iat selects one cell by position.
4

Filter rows with conditions

Conditions let you focus on observations that answer a question. Build masks from comparisons, combine them, and use helpers for categories, ranges, gaps and text matches. Then target an update to the original table with one loc assignment. Filtering and updating share a row condition, but keeping track of which table receives a change is essential under pandas 3 Copy-on-Write.

4.1 Filter with boolean masks

Filtering selects observations that satisfy a question, such as which orders belong to Home and cost more than 10 per item. First create a boolean mask, a Series with one True or False per row. Then use it to select the matching rows.

Build and apply a mask
is_stationery = orders["category"] == "Stationery"
stationery = orders[is_stationery]

The mask is True, False, True, False, False and True. The selection keeps labels 0, 2 and 5, corresponding to orders 1001, 1003 and 1006. Filtering preserves those labels; it does not renumber them. reset_index(drop=True) supplies consecutive labels if needed.

Comparison operators include ==, !=, <, <=, > and >=. Text comparisons match exactly: "home" differs from "Home", and spaces can also prevent a match.

Combine conditions row by row
is_home = orders["category"] == "Home"
is_expensive = orders["unit_price"] > 10
orders[is_home & is_expensive]

Only the Desk lamp qualifies: its category is Home and its price is 18.0. The Mug is Home but costs 6.0. Backpack costs 35.0 but belongs to Bags.

When writing comparisons directly, put each in parentheses:

orders[(orders["category"] == "Home") &
       (orders["unit_price"] > 10)]

Use & for and, | for or and ~ for not. Parentheses keep each comparison together before pandas combines the masks. Without them, Python's precedence rules can try to combine a string and a Series with & and raise TypeError.

Python's and, or and not expect one truth value, not a column of truth values. Using them on masks raises the ambiguous-truth-value ValueError. A plain if orders["quantity"] > 1: has the same problem. Use .any() to ask whether any row matches, or .all() to ask whether every row matches.

Count matches and proportions

is_stationery.sum() is 3 because True counts as 1 and False as 0. is_stationery.mean() is 0.5, the fraction of six orders that match. Multiply by 100 to express that as 50%.

Treat missing values explicitly

With the original float64 quantity column, comparisons involving NaN give False except !=, which gives True. quantity >= 1 keeps five rows; quantity < 1 keeps none. The blank quantity is in neither selection. Yet quantity != 3 includes that blank row, so unequal-to does not mean known-and-different.

After conversion to nullable Int64, comparison with <NA> produces <NA>, and filtering leaves those rows out. Use isna() or notna() when the question concerns gaps.

For selected columns as well as rows, use orders.loc[is_home, "product"]. It returns Desk lamp and Mug. A named mask can be reused for inspecting, counting and updating the same set of rows.

Key Takeaways

  • A comparison creates one boolean result per row; filtering keeps True rows and preserves labels.
  • Combine masks with &, | and ~, with parentheses around comparisons.
  • Use .any() or .all() when a single truth value is required.
  • A boolean mask’s sum counts matches and its mean gives their proportion.
  • Check gaps explicitly: float NaN and nullable <NA> behave differently in comparisons.
  • Text equality is case-sensitive and includes spaces.

4.2 Use helper methods and query for common filters

Some filters have familiar shapes: membership in a list, a numeric interval, a missing value or a text fragment. Helper methods express these tests directly and still produce masks that can be combined with other conditions.

Test membership and ranges
orders[orders["category"].isin(["Home", "Bags"])]
orders[orders["unit_price"].between(4.75, 18)]

isin matches any listed value. The first selection contains orders 1002, 1004 and 1005. ~orders["category"].isin(["Home"]) reverses membership and keeps Stationery and Bags rows. A Python in expression does not make this row-by-row membership mask.

between includes both endpoints by default. The second selection includes Desk lamp at 18.0, Pen set at 4.75 and Mug at 6.0. Use inclusive="neither" to exclude both endpoints, "left" to include only the low endpoint or "right" to include only the high endpoint. Choose the endpoint rule from the question being asked.

Find missing and present entries

orders[orders["quantity"].isna()] keeps order 1006. notna() does the reverse, keeping recorded quantities. Do not test equality with np.nan: NaN is unequal even to itself, so quantity == np.nan does not find the missing row.

Search inside text
orders[orders["product"].str.contains("note", case=False, na=False)]

str.contains tests whether each text value contains a match. Ignoring case finds both Notebook rows. na=False makes missing text count as no match. The search treats its pattern as a regular expression by default; for a literal text fragment with punctuation, regex=False avoids interpreting that punctuation as a pattern. str.startswith and str.endswith test the beginning and end.

Write a filter as a query
orders.query("quantity >= 2 and unit_price < 5")

This keeps orders 1001 and 1003. Within a query string, column names stand for columns and and, or and not are allowed. The string is a pandas query expression; it is not the same syntax as combining Series directly in ordinary Python.

A Python variable needs @:

limit = 5
orders.query("unit_price > @limit")

The result contains Desk lamp, Mug and Backpack. A column name containing a space needs backticks inside the query, as in orders.query("`unit price` > 5").

The same question can be written as a mask, a helper call or a query. Prefer the form that exposes the rule clearly. For an interval, between puts the bounds and inclusion rule together. For a set of allowed labels, isin avoids repeating equality tests. When a filter behaves unexpectedly, inspect the mask and exact column values before changing the condition.

Key Takeaways

  • isin tests membership and ~ reverses the mask.
  • between includes both endpoints unless inclusive changes the rule.
  • isna and notna detect gaps and recorded values.
  • str.contains searches text; case=False ignores case and na=False excludes missing text.
  • Inside query, columns are named directly, Python variables use @ and spaced column names use backticks.

4.3 Change values in selected rows safely

An update needs to target the table you intend to change. In pandas 3, a selection behaves as a separate object under Copy-on-Write, so changing a selected object does not change its parent table.

Put the whole target in one loc assignment
sale = orders.copy()
is_home = sale["category"] == "Home"
sale.loc[is_home, "unit_price"] *= 0.9

The mask selects two Home rows. The column selector targets their prices. Multiplication by 0.9 keeps 90% of each price, reducing 18.00 to 16.20 and 6.00 to 5.40. Other rows are untouched. The expanded form reads the same selection on the right side and assigns its multiplied values on the left.

Here sale is a separate table used for a price change, leaving orders available for comparison. To update the original table, put orders.loc[...] itself on the left of the assignment.

Avoid chained assignment
orders[orders["category"] == "Home"]["unit_price"] = 0

This uses two indexing steps. The first produces a selected object; the second assigns to that object. In pandas 3 it never updates orders, and a ChainedAssignmentError warning points out the problem. The same issue affects orders["unit_price"][1] = 0.

Use orders.loc[orders["category"] == "Home", "unit_price"] = 0 when the intended change is to the original table. The table, matching rows and column are all specified in one assignment.

Understand selected tables

After home = orders[orders["category"] == "Home"], changing home["unit_price"] changes only home. Later changes to orders do not change home either. The objects may share storage internally until a write is needed, but their visible values behave independently.

Older pandas examples may show SettingWithCopyWarning and use .copy() after selection to avoid uncertain updates. pandas 3 removed that warning and makes selection independence consistent. An explicit .copy() is still useful for stating intent, but a selection already behaves independently for updates.

Match the right-side values to the target

A scalar fills all selected cells. A list needs exactly one value per selected row and fills them in selection order. A Series aligns by index label:

new_prices = pd.Series([16.2, 5.4], index=[1, 3])
sale.loc[is_home, "unit_price"] = new_prices

The Home rows have labels 1 and 3, so they receive 16.2 and 5.4. If a selected label were missing from the Series, its assigned value would be NaN; rows outside the selection would remain unchanged. Equal lengths alone do not establish a Series-to-row match.

Inspect sale.loc[is_home, "unit_price"] after the change and compare it with orders.loc[is_home, "unit_price"]. The mask's .sum() is 2, which gives the expected number of targeted rows for this discount.

Key Takeaways

  • Update the intended table through one loc[mask, column] assignment.
  • In pandas 3, chained assignment never updates the original table.
  • Selections behave independently under Copy-on-Write.
  • A scalar fills the selection; a list follows order; a Series aligns by label.
5

Add and transform columns

Derived columns express relationships already present in a table: quantity and price become revenue, while a condition becomes a category label. Use vectorized arithmetic and small transformations to state these rules clearly. You will also choose between mapping every value and replacing a few, keep results through assignment, and account for missing inputs and label alignment when new values enter a table.

5.1 Compute new columns from existing ones

New columns turn recorded data into quantities you can analyze. A calculation between columns works row by row, while the index keeps each result attached to its observation.

Calculate revenue
orders["revenue"] = orders["quantity"] * orders["unit_price"]

The six revenues are 7.5, 18.0, 9.5, 24.0, 35.0 and NaN. For the first row, three items at 2.50 each give 7.50. The last row has an unknown quantity, so its revenue is unknown too. Assigning to a new name adds a column at the right; assigning to an existing name overwrites that column.

Column arithmetic is vectorized. It expresses one rule for the whole column and avoids a Python loop over rows. On large tables this is much faster than for or iterrows, and the expression makes the relationship between inputs clear.

Use the recorded values in a total

orders["revenue"].sum() skips NaN and gives 94.0, the total of the five known revenues. .mean() gives 18.8 because the denominator is five recorded revenues. Dividing 94.0 by all six rows would silently treat the missing revenue as if it contributed a known zero.

To calculate percentage shares:

orders["share_pct"] = (
    orders["revenue"] / orders["revenue"].sum() * 100
).round(1)

The shares are 8.0, 19.1, 10.1, 25.5, 37.2 and NaN. These are shares of the known total. The missing entry remains missing through arithmetic.

Return a table with assign

assign returns a new DataFrame with added or replaced columns, leaving its input unchanged. It works naturally inside a chain:

with_tax = orders.assign(
    tax=lambda d: (d["revenue"] * 0.2).round(2)
)

The lambda reads the table at that point in the chain. It gives tax values 1.5, 3.6, 1.9, 4.8, 7.0 and NaN. In pandas 3, pd.col("revenue") * 0.2 is another way to refer to a column in assign.

Decimal calculations can expose tiny binary floating-point errors: 9.5 times 0.2 can be stored as 1.9000000000000001. .round(2) gives a useful presentation value. Avoid exact equality tests on calculated decimals when small representation errors are possible.

Know how assignment matches rows
orders["home_price"] = orders.loc[
    orders["category"] == "Home", "unit_price"
]

The assigned Series has labels 1 and 3. Those rows receive 18.0 and 6.0; every other row receives NaN. Series assignment matches labels, even when its length differs from the table's. A plain list has no labels and must contain exactly one value per row. A scalar, such as orders["currency"] = "EUR", fills every row.

Derive values from text or dates

The .str and .dt accessors provide vectorized column operations too. orders["product"].str.upper() yields uppercase names, and .str.len() gives lengths 8, 9, 7, 3, 8 and 8. Assign such results to a new column when both the original and derived values are useful.

Key Takeaways

  • Assigning a column expression stores one result per row.
  • Unknown inputs usually produce unknown arithmetic results; summaries skip missing values by default.
  • Vectorized column operations avoid row loops.
  • assign returns a new DataFrame and can refer to columns through a lambda.
  • Series assignment matches labels; list assignment matches row order and length.
  • Use .str and .dt for text and date-derived columns.

5.2 Recode and transform values with np.where, map and apply

Transforming a column can mean applying a numeric rule, assigning a label or translating existing labels. Choose a method whose behavior matches the rule, especially for values the rule does not name.

Turn a condition into labels
orders["price_band"] = np.where(
    orders["unit_price"] >= 5, "high", "low"
)

np.where chooses its second argument where the condition is True and its third where it is False. For prices 2.50, 18.00, 4.75, 6.00, 35.00 and 2.50, the labels are low, high, low, high, high and low. The >= includes a price exactly equal to 5.

Translate all values or change a few
codes = {"Stationery": "ST", "Home": "HM", "Bags": "BG"}
orders["category_code"] = orders["category"].map(codes)

Dictionary map gives ST, HM, ST, HM, BG and ST. A value absent from the dictionary becomes NaN. With only {"Stationery": "ST"}, both Home and Bags become missing. Use a complete mapping when every category needs a translated code.

replace changes listed values and leaves unlisted ones unchanged. orders["category"].replace({"Bags": "Luggage"}) keeps Stationery and Home while renaming Bags.

Intended changeSuitable method
Give each known category a codemap with a dictionary
Rename a few existing labelsreplace
Choose between two outputs from a conditionnp.where
Apply a custom function

A Series can pass each value to a function through map or apply. orders["product"].apply(len) returns each product name's length. Pass len itself; len() would call it immediately without a value.

A lambda can express a small value rule: orders["unit_price"].apply(lambda p: "budget" if p < 5 else "standard"). This returns budget, standard, budget, standard, standard and budget.

For logic needing several cells in one row, DataFrame apply accepts axis=1:

orders.apply(
    lambda r: r["quantity"] * r["unit_price"], axis=1
)

The function reads each row's quantity and price. For this arithmetic, direct column multiplication is clearer and much faster on a large table. Use vectorized expressions or np.where when they can express the calculation; reserve row-wise functions for logic that needs them.

Use built-in numeric transformations

round(n) rounds to n decimal places, abs() gives absolute values and clip(lower=..., upper=...) caps values at limits. orders["unit_price"].clip(upper=20) changes 35.0 to 20.0 and leaves the other five prices unchanged. It does not remove the expensive row.

These transformations return new values. Assign them to a new column to preserve the input for checking, or overwrite the original when that is intended. Inspect a few transformed rows or run value_counts() to check that new labels and their counts fit the rule.

Key Takeaways

  • np.where selects a true-case or false-case output for each condition value.
  • Dictionary map makes unlisted values missing; replace keeps them.
  • Pass a function itself to apply; use axis=1 for a DataFrame row function.
  • Prefer vectorized operations when they express the rule.
  • clip caps values, while round and abs transform them without selecting rows.
6

Sort, rank and summarize data

An ordered table and a compact statistical summary answer different questions about the same observations. Sort records, assign ranks with a deliberate tie rule, and choose counts, centers or spread measures that fit the data. Then examine category proportions and numeric relationships. Missing values, ranking direction, sample denominators and the limits of correlation all affect how a result should be read.

6.1 Sort rows by values or by index

Sorting changes the order in which observations appear. It keeps each row's values together and carries the row label along. Decide what takes priority and how tied values should be ordered before taking a top or bottom selection.

Sort one column
scores = pd.DataFrame({
    "name": ["Ana", "Ben", "Chen", "Dara", "Eli"],
    "points": [88, 92, 88, 75, 92]
})
ordered = scores.sort_values("points")

Smallest comes first by default. Dara's 75 is first, followed by the two 88s and then the two 92s. Row labels move with the records. Among ties, the default sorting algorithm does not guarantee the original order; the displayed labels can read 3, 0, 2, 1, 4, but tied rows must not be assumed to keep that order.

Use ascending=False for largest first. sort_values returns a table, leaving scores unchanged unless its result is assigned.

Choose how ties are resolved
scores.sort_values(
    ["points", "name"], ascending=[False, True]
)

The first key has priority. Points decrease; names increase within equal points. The order is Ben, Eli, Ana, Chen and Dara. Sorting names first would answer a different question because it would make names the primary key.

When one-column ties should preserve input order, use scores.sort_values("points", kind="stable"). Stability keeps tied rows in their existing sequence. A secondary key instead gives ties their own explicit ordering rule.

Place missing values and text

Missing values go last by default in both ascending and descending sorts. pd.Series([3.0, np.nan, 1.0]).sort_values() gives 1.0, 3.0, then NaN. na_position="first" moves the missing entry to the beginning; reversing sort direction alone does not do that.

Text sorting follows character codes. "Zebra" sorts before "apple" because uppercase and lowercase letters occupy different ranges. Consistently written names such as Bags, Home and Stationery sort in the expected alphabetical order.

Sort labels or renumber them

sort_index() orders the row labels, not the data values. After sorting by points, it can restore the original default-label order. sort_index(ascending=False) reverses label order. By contrast, reset_index(drop=True) leaves the current row order in place and replaces its labels with 0, 1, 2 and so on.

Select the largest or smallest rows

scores.nlargest(2, "points") returns Ben and Eli, both with 92. nsmallest takes low values instead. If the cut falls inside a tie, decide whether to keep every tied row. scores.nlargest(1, "points", keep="all") returns both 92s, even though n is 1. The number requested is then a cutoff, not a promise about the final row count.

Key Takeaways

  • sort_values orders rows by data values; sort_index orders row labels.
  • ascending=False puts large values first, while missing values still go last by default.
  • Multiple sort keys apply in priority order and can use different directions.
  • Use a secondary key or a stable one-column sort when tie order matters.
  • reset_index(drop=True) renumbers the current order without re-sorting it.
  • keep="all" in a top-value selection can return more than n rows.

6.2 Rank values and handle ties

A rank records where a value belongs in sorted order without moving its row. It is useful when each observation needs a place number alongside its original data. Ties need a rule because several values can occupy the same part of that order.

Choose the direction

scores["points"].rank() ranks from smallest to largest. Use ascending=False for a results table where high scores should get the best ranks. The tie method then decides which place number each tied group receives.

The example scores in row order are Ana 88, Ben 92, Chen 88, Dara 75 and Eli 92. In descending order, the 92s occupy places 1 and 2, the 88s places 3 and 4, and 75 place 5. The default method="average" assigns each tied value the mean of its occupied places. The returned values, in original row order, are 3.5, 1.5, 3.5, 5.0 and 1.5.

Pick a tie method
MethodDescending ranks in original row orderTie rule
average3.5, 1.5, 3.5, 5.0, 1.5Average of occupied ranks
min3, 1, 3, 5, 1Smallest occupied rank
max4, 2, 4, 5, 2Largest occupied rank
dense2, 1, 2, 3, 1One rank per distinct value, no gaps
first3, 1, 4, 5, 2Separate ranks in appearance order

With min, two winners at rank 1 mean the next score starts at rank 3. With dense, the next distinct score starts at rank 2. first breaks a tie even when the scores themselves provide no basis for preferring one person; it follows input order.

Rank results are floats, allowing values such as 1.5. When a chosen tie method gives whole-number ranks and none are missing, .astype(int) converts them for display. An ordinary integer dtype cannot hold a missing rank.

Express ranks as fractions

For the default average method and non-missing values, rank(pct=True) divides each rank by the number of ranked values. Ranking the five example scores ascending gives 2.5, 4.5, 2.5, 1.0 and 4.5. Dividing by five gives 0.5, 0.9, 0.5, 0.2 and 0.9.

The tied highest values receive 0.9, not 1, because their average rank is 4.5. A percentile rank describes rank relative to the ranked values; it is not a percentage of the score itself.

Handle missing ranks and store results

Missing values retain NaN ranks by default. With revenues 7.5, 18.0, 9.5, 24.0, 35.0 and NaN, descending ranks are 5, 3, 4, 2, 1 and NaN. na_option="bottom" puts the missing entry after recorded values, giving it rank 6.

scores["place"] = scores["points"].rank(
    method="min", ascending=False
)

The rows remain Ana, Ben, Chen, Dara and Eli. The new place column records 3, 1, 3, 5 and 1. Sort separately if the display should show winners first.

Key Takeaways

  • Ranking assigns places without moving rows; descending ranking gives large values low rank numbers.
  • Tie methods control whether shared ranks leave gaps or follow input order.
  • The default average method can return fractional ranks.
  • With default average ranking, pct=True divides by the number of ranked values.
  • Missing values keep missing ranks by default; na_option="bottom" ranks them last.

6.3 Summarize columns with descriptive statistics

A descriptive statistic compresses many observations into one useful quantity. Choose a statistic that fits the question, and read its non-missing count so you know how much data supports it.

Compute centers and spread
weather = pd.DataFrame({
    "temp_c": [14.0, 17.5, 16.0, 21.0, 19.5, 12.5, 15.0],
    "rain_mm": [0.0, 2.4, 0.0, 0.0, 5.1, 12.3, 0.8]
}, index=["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"])

For weather["temp_c"], sum() is 115.5, mean() is 16.5 and median() is 16.0. The minimum is 12.5 and maximum 21.0, giving a range of 8.5 °C. idxmax() returns the label "Thu", while idxmin() returns "Sat": they identify observations instead of returning the extreme values themselves.

std() and var() measure spread. pandas uses the sample denominator by default, ddof=1, dividing squared deviations by one less than the count. Here standard deviation is about 3.028 °C and variance about 9.167 squared degrees Celsius. std(ddof=0) uses the count itself and gives about 2.803 °C. NumPy's np.std defaults to ddof=0, so match the setting before comparing results.

Read quartiles and describe

quantile(0.25) gives the lower quartile, 14.5; quantile(0.5) gives the median, 16.0; quantile(0.75) gives the upper quartile, 18.5. The default interpolation can return a value between recorded readings.

weather.describe() combines count, mean, standard deviation, minimum, the three quartiles and maximum for numeric columns. Rain has mean about 2.94 mm and median 0.8 mm. The 12.3 mm reading pulls the mean upward; the median better describes a typical day in this right-skewed week.

Account for missing values and types

For pd.Series([1, np.nan, 3]), .mean() is 2.0 because missing values are skipped by default. .count() is 2, while .size is 3. With skipna=False, the mean is NaN. Do not use total row count as the denominator for the default mean when some entries are missing.

Text summaries differ. orders["category"].describe() gives count 6, unique 3, top Stationery and freq 3. Averaging the mixed-text orders table raises TypeError; use orders.mean(numeric_only=True) or select numeric columns with select_dtypes("number").

Summarize along an axis

By default, DataFrame statistics reduce down rows to one result per column. axis=1 instead gives one result per row; select quantities whose units can sensibly be combined.

orders[["quantity", "unit_price"]].agg(["mean", "max"])

agg computes several named statistics together. Quantity has mean 2.2 and maximum 4.0; unit_price has mean about 11.46 and maximum 35.0. weather["rain_mm"].cumsum() gives running totals 0.0, 2.4, 2.4, 2.4, 7.5, 19.8 and 20.6 mm, preserving one result per day.

Key Takeaways

  • Choose totals, centers or spread measures to match the question.
  • describe collects common numeric statistics; text columns have frequency-based summaries.
  • count excludes missing values, while size includes them.
  • pandas standard deviation uses ddof=1; NumPy defaults to ddof=0.
  • Quantiles can interpolate between readings.
  • idxmax and idxmin return labels; cumsum returns running totals.
  • agg requests several statistics, and axis controls the direction of reduction.

6.4 Count values and measure relationships

Counts describe how often values occur; correlations describe how two numeric variables vary together. Both summaries need interpretation: what is being counted, what is missing and which relationship the statistic measures.

Count categories or list distinct values

orders["category"].value_counts() gives Stationery 3, Home 2 and Bags 1, ordered by frequency. The returned Series is named count. Missing entries are excluded by default; dropna=False includes them as a separate count.

orders["category"].value_counts(normalize=True)

The normalized Series is named proportion: Stationery is 0.5, Home about 0.333 and Bags about 0.167. Multiplying by 100 expresses percentages. With the default missing-value rule, these shares describe present values.

QuestionMethod
How often does each value occur?value_counts()
Which distinct values occur?unique()
How many distinct present values occur?nunique()
Which value or values occur most often?mode()

unique() keeps first-appearance order: Stationery, Home, Bags. mode() returns a Series because several values can tie for the highest frequency. It is not a request for a single arbitrarily chosen winner.

Conditions can be counted directly. (weather["rain_mm"] > 0).sum() counts four rainy days. Its .mean() is about 0.571, so about 57% of the seven days had rain.

Measure a straight-line relationship

weather["temp_c"].corr(weather["rain_mm"]) gives a Pearson correlation of about −0.397. Its negative sign says that warmer days tended to have less rain in these observations. Its magnitude describes how closely a straight-line pattern fits, on a scale from −1 through 0 to 1.

A value of 1 means a perfect increasing straight-line relationship; −1 means a perfect decreasing one. A value near zero means little linear association. A curved relationship can still be strong even when Pearson correlation is near zero. Correlation is also about association, not evidence that changing one variable causes the other to change.

Read a correlation matrix

weather.corr() gives all numeric pairs together. The matrix is symmetric: temperature with rain has the same correlation as rain with temperature. A varying numeric column has correlation 1 with itself; a constant column has no defined correlation and gives NaN instead.

For relationships that consistently increase or decrease without following a straight line, method="spearman" computes correlation from ranks. The method changes what kind of pattern is summarized, so name it when reporting a result.

The weather calculation uses only seven readings. It describes this small observed week; strong claims about a wider climate pattern need more evidence. A useful report includes the variables, the sign and size of the coefficient, the method and the number of observations.

Key Takeaways

  • value_counts reports frequencies; normalization reports proportions of counted values.
  • unique, nunique and mode answer different questions about distinct and frequent values.
  • A condition’s sum counts matches and its mean gives a proportion.
  • Pearson correlation measures linear association from −1 to 1.
  • A correlation matrix is symmetric; constant columns give undefined correlations.
  • Spearman correlation works on ranks, and correlation alone establishes no cause.

Getting Started with pandas examples

6 Walkthroughs

1

Build a table whose labels make sense

12 steps
Create labeled data, predict alignment and choose an index for reliable lookups.
  1. 1
    IntroductionKeep values attached to their meaning

    A list gives values in an order. pandas adds labels so you can identify what each value describes, even after rows move. Start with one labeled variable, then combine several variables into a table.

    The key question is whether an operation follows a row’s identity or its current position. That distinction explains both Series arithmetic and choosing a useful table index.

  2. 2
    ExampleBuild a labeled rain Series

    Create three rain readings in millimeters:

    rain = pd.Series([4.5, 3.0, 6.2],
        index=["Mon", "Tue", "Wed"], name="rain_mm")
    

    The values and labels are paired in order. rain["Tue"] gives 3.0, while rain.iloc[0] gives 4.5. The first request names a day; the second names a position. .dtype is float64, and .size is 3.

  3. 3
    ExplanationApply a rule to every value

    A Series supports vectorized operations: rain * 2 doubles every reading and keeps the day labels. rain > 4 produces True, False and True, again labeled by day.

    Use attributes such as .index, .name and .dtype without parentheses. When you need the values as a NumPy array, call .to_numpy(); .values can return a pandas array for some dtypes.

  4. 4
    ExampleAdd by label, not displayed row

    Let a contain x 1, y 2 and z 3, while b contains y 10, z 20 and w 30. In a + b, y pairs with y, giving 12.0, and z pairs with z, giving 23.0.

    The labels x and w have no partner, so their results are NaN. a.add(b, fill_value=0) instead gives x 1.0 and w 30.0. A shared row position does not pair entries with different labels.

  5. 5
    ChallengePredict an aligned sum

    A Series has labels a and b with values 4 and 7. Another has labels b and c with values 3 and 9. What are the non-missing results of ordinary addition?

    ---reveal---

    Only b is present in both inputs. Its sum is 7 plus 3, giving 10.0. Labels a and c have missing results. Adding first-to-first would incorrectly pair a with b.

  6. 6
    ExampleBuild several variables into columns

    Create a small order table:

    df = pd.DataFrame({"product": ["Notebook", "Mug"],
        "quantity": [3, 4], "unit_price": [2.5, 6.0]})
    

    Each list supplies one column and must have one value per row. The columns share index labels 0 and 1 but keep their own dtypes. .shape is (2, 3), while .size is 6 because it counts every cell.

  7. 7
    Key InsightKeep the shape your next step needs

    df["quantity"] returns a Series. df[["quantity"]] returns a one-column DataFrame because the inner list requests a collection of columns.

    This is a difference in structure, even though the visible values match. Square brackets also avoid name collisions: a column called size needs df["size"], since df.size means the DataFrame’s cell count.

  8. 8
    ChallengeChoose the direction of a total

    For columns a [1, 2] and b [3, 4], what does a row-wise sum return, and which axis requests it?

    ---reveal---

    Use df.sum(axis=1). The first row gives 1 plus 3, or 4; the second gives 2 plus 4, or 6. The default axis works down the rows and would instead give column totals a 3 and b 7.

  9. 9
    ExampleUse the order ID as the index

    For a table with an order_id column, save by_id = orders.set_index("order_id"). The order numbers move into the row index and out of the ordinary columns.

    A lookup such as by_id.loc[1004] now names an order instead of its current location. Check by_id.index.is_unique before relying on each number to identify exactly one row; pandas permits duplicate labels.

  10. 10
    TipSave a label change

    rename, drop, set_index and reset_index return new tables. Keep the result with assignment, such as orders = orders.rename(columns={"unit_price": "price"}).

    A missed assignment leaves the old table in place. A misspelled old column name in rename is ignored by default, so inspect .columns when the expected new name is absent.

  11. 11
    ChallengeRestore IDs without losing them

    A table uses order IDs as its index. You need a default row index and still need the IDs as data. What operation should you save?

    ---reveal---

    Save df = df.reset_index(). It preserves the old index as a column and supplies labels 0, 1, 2 and so on. Using drop=True would discard those IDs instead. The row order remains the same.

  12. 12
    RecapPredict identity, type and shape

    Before reading a result, check three things: which labels identify its values, what dtype stores them and how many axes the selection keeps.

    Series arithmetic follows labels. A DataFrame organizes variables in typed columns. Index changes let a meaningful ID support later lookups, provided the returned table is saved and its labels identify rows uniquely.

2

Load a CSV and check its meaning

13 steps
Read a file, trace structural problems and keep useful numeric and date types.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionTreat loading as a checkable step
  2. 2
    ExplanationRead records into a table
  3. 3
    ExampleMatch separators and decimal marks
  4. 4
    TipPreserve codes during reading
  5. 5
    ChallengeKeep the first record
  6. 6
    ExampleCheck the visible layout
  7. 7
    ExplanationCount what is present and missing
  8. 8
    ChallengeCheck an ID and a measurement
  9. 9
    ExampleConvert numeric text and trace a failure
  10. 10
    Key InsightKeep missing counts as integers
  11. 11
    ExampleMake date operations available
  12. 12
    ChallengeRepair a numeric import
  13. 13
    RecapConnect layout, types and counts
3

Pick rows by identity or location

10 steps
Compare loc and iloc, predict slice endpoints and keep the result shape you need.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionAsk whether identity or location matters
  2. 2
    ExampleRead a known order
  3. 3
    ExampleRead an inclusive label range
  4. 4
    ChallengeKeep a one-row table
  5. 5
    ExampleRead a positional range
  6. 6
    TipRead backward and beyond the end
  7. 7
    ChallengePredict one row versus one value
  8. 8
    ConnectionUse a short form for one cell
  9. 9
    ChallengeFollow a row through a sort
  10. 10
    RecapState both the selector and the shape
4

Filter records and update the right table

13 steps
Build a condition, combine tests and make a targeted change under Copy-on-Write.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionTurn a data question into a row test
  2. 2
    ExampleBuild a boolean mask
  3. 3
    ExplanationRequire both conditions
  4. 4
    TipUse one truth value only when needed
  5. 5
    ChallengeCount a combined condition
  6. 6
    ExampleExpress a range directly
  7. 7
    Key InsightFind gaps with a missing-value test
  8. 8
    ChallengeTranslate a filter into query
  9. 9
    ExampleDiscount exactly the Home prices
  10. 10
    ExplanationSee why a chain misses the parent
  11. 11
    TipMatch update values by label
  12. 12
    ChallengeCombine filtering and an update
  13. 13
    RecapMake conditions and targets explicit
5

Turn existing columns into useful new data

12 steps
Calculate revenue, retain missing values and choose suitable mapping and transformation methods.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionExpress a rule once for each column
  2. 2
    ExampleCalculate one revenue per order
  3. 3
    Key InsightRead the denominator behind a mean
  4. 4
    ExampleAdd a column within a chain
  5. 5
    ChallengePlace an incoming Series
  6. 6
    ExampleChoose labels from a threshold
  7. 7
    ExplanationDecide what unlisted values mean
  8. 8
    ChallengeChoose a partial recoding method
  9. 9
    TipPass functions without calling them
  10. 10
    ExampleCap values without removing records
  11. 11
    ChallengeTrace a computed and recoded column
  12. 12
    RecapCheck the rule and its unmatched inputs
6

Order data and interpret its summaries

18 steps
Trace sorting and ranking rules, then calculate and interpret numeric and categorical summaries.

Save this lesson to follow every Walkthrough step by step.

  1. 1
    IntroductionChoose the view that answers the question
  2. 2
    ExampleSort points before names
  3. 3
    TipKeep a complete boundary tie
  4. 4
    ChallengeSeparate label order from value order
  5. 5
    ExampleAverage the places occupied by ties
  6. 6
    ExplanationChoose gaps or consecutive groups
  7. 7
    ChallengeRead a percentile rank
  8. 8
    ExampleBuild a weather summary
  9. 9
    ExplanationMatch the spread denominator
  10. 10
    ExampleRead quartiles and a skewed mean
  11. 11
    ChallengeCheck a mean against its count
  12. 12
    ExampleCount categories and proportions
  13. 13
    Key InsightSeparate three questions about values
  14. 14
    ChallengeCount a condition as a fraction
  15. 15
    ExplanationDescribe association precisely
  16. 16
    ChallengeRead a matrix after checking the data
  17. 17
    ChallengeChoose and report a summary
  18. 18
    RecapKeep each summary’s rule visible

Getting Started with pandas practice questions

50 Practice Questions in 5 sets

Set 1: Read and use a pandas table10 Practice Questions

Question 1 of 10

A table has unique row labels [30, 10, 20]. Which row does df.loc[10] select?
  1. The row labeled 10, now second.
  2. The first row, at position zero.
  3. The last row, at position two.
  4. The tenth row, if it exists.
Show answerHide answer
Answer: A
loc interprets 10 as an index label, so it selects the second displayed row. It does not count forward ten positions. The row’s location can change after sorting, but its label remains the same until the index is explicitly changed.

Question 2 of 10

df has category values ["A", "B", "A", "B"] and masses [3, 7, 9, 4]. Which labels pass (df["category"] == "A") | (df["mass_kg"] > 6) with the default index?
  1. Only label 2.
  2. Only labels 0 and 2.
  3. Labels 0, 1 and 2.
  4. Only labels 1 and 2.
Show answerHide answer
Answer: C
The or mask keeps rows meeting either condition. Rows 0 and 2 are category A, and rows 1 and 2 exceed 6 kg, so their union is 0, 1 and 2. Keeping only label 2 would require both conditions and would use & instead of |.

Question 3 of 10

Quantities are [2.0, 5.0, NaN] and unit prices [7.0, 3.0, 9.0]. What is the default mean of their row-wise products?
  1. About 9.67
  2. 14.5
  3. 29.0
  4. NaN
Show answerHide answer
Answer: B
The products are 14, 15 and NaN. The default mean skips the missing result, so 29 is divided by two to give 14.5. Dividing by all three rows gives about 9.67 and would treat an unknown revenue as though its contribution were a recorded zero.

Question 4 of 10

A column contains [4.0, NaN, 9.0] and represents whole item counts. What dtype can retain the gap while storing known counts as integers?
  1. int
  2. "bool"
  3. "str"
  4. "Int64"
Show answerHide answer
Answer: D
Nullable Int64, with a capital I, stores whole numbers and represents the missing entry as <NA>. Ordinary int64 has no missing marker and cannot convert this NaN. Text would preserve a display of the entries but would not store numeric integer counts.

Question 5 of 10

s = pd.Series([8, 13, 5], index=[2, 0, 1]). What does s[0] return?
  1. 8
  2. 13
  3. 5
  4. 0
Show answerHide answer
Answer: B
The integer key 0 selects index label 0, whose value is 13. The first displayed value is 8, but that is at position 0 and label 2. To ask for the first value by position, use s.iloc[0]; integer keys in square brackets remain labels.

Question 6 of 10

A numeric column contains [5.0, NaN, 2.0]. In a default descending value sort, where does NaN appear?
  1. Before both numeric values.
  2. Between the two numeric values.
  3. After both numeric values.
  4. In the same position as before.
Show answerHide answer
Answer: C
Missing values go last by default even when values are sorted descending. The order is 5, 2, then NaN. Reversing ascending changes the numeric order but does not move gaps to the front; that requires na_position="first".

Question 7 of 10

a = pd.Series([6, 9], index=["east", "west"]) and b = pd.Series([4, 7], index=["west", "east"]). What are (a + b).loc["east"] and (a + b).loc["west"]?
  1. 13 and 13
  2. 10 and 16
  3. 6 and 9
  4. 7 and 4
Show answerHide answer
Answer: A
Series arithmetic matches index labels. East combines 6 with 7 and west combines 9 with 4, so both sums are 13. Pairing the first displayed entries would give 10 and 16, but those entries belong to different labels and are not paired by pandas.

Question 8 of 10

Two rows have missing cells: one has gaps in three columns and the other in one column. What does df.isna().any(axis=1).sum() return?
  1. 4
  2. 3
  3. 1
  4. 2
Show answerHide answer
Answer: D
any(axis=1) reduces each row to one answer: whether it contains at least one gap. Both affected rows are True, so the sum is 2. Adding the missing counts across all columns would give four cells, but this expression counts rows only once.

Question 9 of 10

Names are ["Zoe", "Ari", "Bo", "Dee"] with scores [8, 8, 10, 8]. After sorting by score descending and name ascending, then taking the first two rows, which names appear in order?
  1. Bo, Zoe.
  2. Bo, Ari.
  3. Ari, Bo.
  4. Ari, Dee.
Show answerHide answer
Answer: B
Bo’s 10 puts Bo first. The three scores of 8 are then ordered by name, with Ari before Dee and Zoe, so the second selected row is Ari. Keeping Zoe second would preserve input order within the tie instead of applying the stated secondary key.

Question 10 of 10

s contains ["A", "B", "C", "A", "B"]. After s.replace({"C": "B"}), what are the mode and its normalized frequency?
  1. B and 0.6.
  2. A and 0.4.
  3. B and 0.5.
  4. A and 0.6.
Show answerHide answer
Answer: A
Replacing C with B makes the counts A 2 and B 3, so B is the mode. Its normalized frequency is three out of five, or 0.6. The denominator remains five because replace keeps every observation; the transformation does not remove the original C row.
Set 2: Choose the right pandas operation10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A DataFrame has 7 rows and 4 columns. What is its .size?
  1. 7
  2. 4
  3. 28
  4. 11
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

An 11-row table has a column with 8 non-null values. How many values are missing in that column?
  1. 3
  2. 8
  3. 11
  4. 19
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

df has five rows. What row positions are selected by df.iloc[1:4]?
  1. Positions 1, 2, 3 and 4.
  2. Positions 1, 2 and 3.
  3. Positions 0, 1 and 2.
  4. Positions 2, 3 and 4.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

In pandas 3, chosen = df[df["active"]] is followed by chosen["score"] = 0. What happens to df?
  1. All of its scores become zero.
  2. Only active scores become zero.
  3. Only inactive scores become zero.
  4. Its score values stay unchanged.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

For values [4, 6, 9], what labels result from np.where(s >= 6, "large", "small")?
  1. ["small", "small", "large"]
  2. ["small", "large", "large"]
  3. ["large", "small", "small"]
  4. ["large", "large", "small"]
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

Scores [90, 70, 90, 50] are ranked with method="min", ascending=False. What ranks result in original row order?
  1. [1, 3, 1, 4]
  2. [1, 2, 1, 3]
  3. [1.5, 3, 1.5, 4]
  4. [2, 3, 2, 4]
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A semicolon file contains code;mass_kg, then 007;1,5 and 012;2,0. Which load preserves the codes and permits a numeric mean mass?
  1. pd.read_csv("loads.csv", sep=";", decimal=".", dtype={"code": str})
  2. pd.read_csv("loads.csv", sep=";", decimal=",", dtype={"code": int})
  3. pd.read_csv("loads.csv", sep=";", decimal=",", dtype={"code": str})
  4. pd.read_csv("loads.csv", sep=",", decimal=",", dtype={"code": str})
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

df has index [10, 20, 30] and revenue [12.0, 24.0, 36.0]. A new column is assigned df.loc[df["revenue"] > 15, "revenue"] / 2. What is the new column’s default sum?
  1. 36.0
  2. 18.0
  3. NaN
  4. 30.0
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

Values [12, 4, 12, 8] are ranked ascending with the default method and pct=True. What percentile rank belongs to each 12?
  1. 1.0
  2. 0.75
  3. 0.875
  4. 0.5
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

df.index is ["a", "b", "a"]. What is the type of df.loc["a"]?
  1. A DataFrame containing two rows.
  2. A Series with the first row only.
  3. A Series holding the last row.
  4. A scalar counting the matching rows.
Show answerHide answer

Save this lesson to see this answer.

Set 3: Check rows, types and calculations10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

df has an unnamed index [40, 60]. What does df.reset_index() do with those labels?
  1. Discards them and keeps all other columns.
  2. Keeps them as the new row labels.
  3. Uses them to rename the first column.
  4. Keeps them in an index column.
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A file has no header and begins 501,Sensor. How should it be loaded with columns id and device without losing that first record?
  1. pd.read_csv("devices.csv", header=0, names=["id", "device"])
  2. pd.read_csv("devices.csv", header=None, names=["id", "device"])
  3. pd.read_csv("devices.csv", skiprows=1, names=["id", "device"])
  4. pd.read_csv("devices.csv", index_col=0, names=["id", "device"])
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

On an ordered index [11, 12, 13, 14], df.loc[12:14, ["mass_kg"]] has what shape?
  1. (3, 1)
  2. (2, 1)
  3. (1, 3)
  4. (3,)
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

cutoff = 6. How can query select rows whose mass_kg exceeds that Python variable?
  1. df.query("mass_kg > cutoff")
  2. df.query("@mass_kg > cutoff")
  3. df.query("mass_kg > @cutoff")
  4. df.query("mass_kg > 6@")
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

What happens to 14 in pd.Series([-2, 6, 14]).clip(lower=0, upper=10)?
  1. It becomes 10.
  2. It is removed.
  3. It becomes 0.
  4. It stays 14.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

A text Series is ["L", "M", "L", None]. What proportion does default value_counts(normalize=True) assign to L?
  1. 0.5
  2. 0.75
  3. 2.0
  4. About 0.667
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

a = pd.Series([5, 8], index=["u", "v"]) and b = pd.Series([2, 4], index=["v", "w"]). Let c = a.add(b, fill_value=0). What is c[c > 4].sum()?
  1. 10.0
  2. 15.0
  3. 19.0
  4. 9.0
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A six-row import has six distinct non-missing IDs and four present temperature readings totaling 28 °C. A report says that an ID repeats and the mean is about 4.67 °C. What corrected report fits the data?
  1. An ID repeats; two readings are missing; mean is 7 °C.
  2. IDs are unique; no readings are missing; mean is 4.67 °C.
  3. IDs are unique; two readings are missing; mean is 7 °C.
  4. An ID repeats; no readings are missing; mean is 4.67 °C.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

df has index [4, 8, 12] and float prices [10.0, 20.0, 30.0]. A mask selects labels 4 and 12. After df.loc[mask, "price"] = pd.Series([7.0, 9.0], index=[12, 4]), what are prices in original row order?
  1. [7.0, 20.0, 9.0]
  2. [9.0, 20.0, 7.0]
  3. [9.0, NaN, 7.0]
  4. [NaN, 20.0, NaN]
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

Scores are [11, 9, 9, 6]. What is the number of rows and smallest score returned by df.nlargest(2, "score", keep="all")?
  1. 2 rows; smallest score 9.
  2. 4 rows; smallest score 6.
  3. 1 row; smallest score 11.
  4. 3 rows; smallest score 9.
Show answerHide answer

Save this lesson to see this answer.

Set 4: Trace several operations together10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

df = pd.DataFrame({"a": [2, 5], "b": [7, 1]}). What values does df.sum(axis=1) return in row order?
  1. [9, 6]
  2. [7, 8]
  3. [3, 12]
  4. [2, 5, 7, 1]
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

s = pd.Series(["8", "bad", "2.5"]). What are the values after pd.to_numeric(s, errors="coerce")?
  1. [8.0, 0.0, 2.5]
  2. [8, "bad", 2.5]
  3. [8.0, NaN, 2.5]
  4. [8, NaN, 2]
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A table has index [7, 2, 9] and x values [4, 12, 8]. Let d = df.sort_values("x", ascending=False). What is d.iloc[:2]["x"].sum() - d.loc[7, "x"]?
  1. 20
  2. 8
  3. 24
  4. 16
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

For masses [2, 5, 8], which values pass .between(2, 8, inclusive="neither")?
  1. Both 2 and 5.
  2. Only 5.
  3. Both 5 and 8.
  4. All three values.
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

df has index [5, 9, 12], quantity [2, 3, 4] and price [6, 5, 2]. It assigns revenue, keeps revenues above 10, then assigns pd.Series([20.0], index=[9]) as adjusted. What is the default mean adjusted value?
  1. 10.0
  2. 13.5
  3. 20.0
  4. NaN
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

Readings are [3.0, 7.0, NaN, 8.0]. What are their default mean and count?
  1. 4.5 and 4
  2. 6.0 and 3
  3. 6.0 and 4
  4. 4.5 and 3
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

df = pd.DataFrame({"a": [2, 6], "b": [5, 3]}, index=[8, 4]). After df = df.T, what are df.shape and df.loc["b"].sum()?
  1. (2, 2) and 8
  2. (2, 2) and 9
  3. (2, 2) and 7
  4. (4, 1) and 8
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

A Series holds "1,500", "800", "unknown", "200", with no existing gaps. After removing commas, numeric coercion and taking the default mean, what are the mean and number of new gaps?
  1. 625.0; one new gap.
  2. About 833.33; no new gaps.
  3. 625.0; no new gaps.
  4. About 833.33; one new gap.
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A float64 Series contains [2.0, NaN, 8.0, 5.0]. What is the sum of values selected by s.notna() & (s != 5) & (s < 8)?
  1. 10.0
  2. 7.0
  3. 2.0
  4. NaN
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

Readings are [1, 2, 3, 4, 40] mm. The mean is 10 mm and the median is 3 mm. Why is the median a better description of a typical reading here?
  1. The median adds the five readings before dividing.
  2. The mean gives each reading a different weight.
  3. The median always equals the smallest reading.
  4. The high 40 mm reading pulls the mean upward.
Show answerHide answer

Save this lesson to see this answer.

Set 5: Resolve alignment and summary problems10 Practice Questions

Save this lesson to see every answer and practice every set.

Question 1 of 10

A table indexed by unique IDs 81 and 82 is saved as df. The next line is df.reset_index(). Why does df.loc[0] still fail?
  1. The reset kept 81 as the first label.
  2. The new index begins at position 1.
  3. The returned table was not assigned.
  4. The ID column prevents label lookup.
Show answerHide answer

Save this lesson to see this answer.

Question 2 of 10

A file uses semicolons between fields and decimal points in numbers. What option changes the field separator?
  1. decimal=";"
  2. sep=";"
  3. header=";"
  4. index_col=";"
Show answerHide answer

Save this lesson to see this answer.

Question 3 of 10

A four-row table has labels [8, 3, 6, 1]. What labels remain in df.iloc[-2:][["x"]]?
  1. 8 and 3.
  2. 3 and 6.
  3. 1 and 6.
  4. 6 and 1.
Show answerHide answer

Save this lesson to see this answer.

Question 4 of 10

df has index ["k", "m", "p"], a [4, 8, 12] and b [3, 1, 5]. Let d = df.loc[(df["a"] >= 8) & (df["b"] < 4), ["a", "b"]]. What is d.sum(axis=1).iloc[0]?
  1. 9
  2. 7
  3. 17
  4. 24
Show answerHide answer

Save this lesson to see this answer.

Question 5 of 10

Device names are ["Probe A", "sensor", None, "PROBE B"]. Which default row labels pass .str.contains("probe", case=False, na=False)?
  1. 0 and 3.
  2. Only label 0.
  3. 0, 2 and 3.
  4. Only label 3.
Show answerHide answer

Save this lesson to see this answer.

Question 6 of 10

df has default labels and float prices [8.0, 12.0, 18.0]. mask = df["price"] >= 12, then df.loc[mask, "price"] = pd.Series([9.0], index=[2]). What does df["price"].count() return?
  1. 3
  2. 2
  3. 1
  4. 0
Show answerHide answer

Save this lesson to see this answer.

Question 7 of 10

A table has the default index and scores [60, 90, 90, 75] in row order. A descending dense rank is assigned as place, and the table is sorted by place ascending with a stable sort. What original row labels appear first?
  1. 0 and 3.
  2. 2 and 1.
  3. 1 and 3.
  4. 1 and 2.
Show answerHide answer

Save this lesson to see this answer.

Question 8 of 10

s = pd.Series(["X", "Y", "X", "Z"]). After t = s.map({"X": 4, "Y": 10}), what are t.count() and t.mean()?
  1. 4 and 4.5
  2. 3 and 4.5
  3. 3 and 6.0
  4. 4 and 6.0
Show answerHide answer

Save this lesson to see this answer.

Question 9 of 10

A pandas Series s contains [2.0, 4.0, 6.0]. What are s.std() and np.std(s.to_numpy()), rounded to three decimal places?
  1. 1.633 and 2.000
  2. 4.000 and 2.667
  3. 2.000 and 2.000
  4. 2.000 and 1.633
Show answerHide answer

Save this lesson to see this answer.

Question 10 of 10

df has x [1, 2, 3, 4], y [100, 6, 4, 2] and z [5, 5, 5, 5]. After df.loc[df["x"] > 1, ["x", "y", "z"]].corr(), what values appear for x with y and z with itself?
  1. 1.0 and NaN
  2. -1.0 and 1.0
  3. -1.0 and NaN
  4. -1.0 and 0.0
Show answerHide answer

Save this lesson to see this answer.

Stuck on your own question? Homework Help

Key Terms

91 Key Terms, each with its definition

A

Aggregation
An aggregation reduces a collection of values to summary results, with agg allowing several statistics to be requested together.
agg(["mean", "max"]) reports two different summaries for each selected numeric column.
Appearance-order rank
An appearance-order rank breaks ties by their order in the input, giving each tied entry a separate rank with method first.
Reordering tied rows can change their first-method ranks even though their scores are unchanged.
Ascending order
Ascending order places smaller values before larger ones, the default direction of pandas value and index sorting.
Set ascending=False when a results table should display the highest points first.
assign
The assign method returns a DataFrame containing new or replaced columns and leaves its input table unchanged.
An assign lambda can calculate a tax column from revenue at that stage in a method chain.
Association
An association is an observed relationship between variables; a correlation describes it without establishing a causal mechanism.
A week’s temperature-rain correlation does not show that changing temperature would cause a rainfall change.
at
The at indexer selects a single cell by its row and column labels, providing a concise form of scalar label lookup.
orders.at[2, "product"] reads the product at label 2 in a default-indexed orders table.
Average rank
An average rank gives every tied value the mean of the positions occupied by its tied group in sorted order.
Two equal highest scores occupying places 1 and 2 both receive descending rank 1.5.
Axis
An axis is a direction in a pandas table: axis 0 runs along rows, and axis 1 runs along columns for row-wise reductions.
df.sum(axis=1) adds the selected numeric columns within each row, giving one total per row.

B

between
The between method tests whether each value lies within a lower and upper bound, including both endpoints by default.
between(5, 20, inclusive="left") includes 5 but excludes 20 from the price interval.
Boolean mask
A boolean mask is a sequence of truth values indicating which entries satisfy a condition and should be selected.
Comparing each price with 10 creates one True or False for each order’s row.
Boolean reduction
A boolean reduction combines many truth values into one result, such as whether any or all entries are True.
A mask’s .any() can answer whether at least one order has a missing quantity.
Broadcasting a scalar
Broadcasting a scalar applies one supplied value throughout a column operation or fills a targeted column with that value.
Dividing every revenue by the same known total gives each order’s share of that total.

C

Category dtype
The category dtype represents repeated labels through a set of categories and their codes, usually saving memory on large tables.
An unordered category column rejects min() even when its displayed labels are ordinary text.
Chained assignment
Chained assignment tries to update values through successive selections and never changes the original table in pandas 3.
A filtered table followed by another column selection cannot serve as an update to its parent.
Clipping
Clipping caps values at given lower or upper limits, retaining each observation instead of removing out-of-range rows.
Clipping unit prices at 20 changes a value of 35 to 20 while keeping the same order record.
Coercion
Numeric coercion converts parseable numeric values and replaces invalid entries with missing values instead of stopping.
Converting "7", "unknown", "2.5" with errors set to coerce creates one new missing entry.
Column
A column is a labeled sequence representing one variable in a DataFrame, stored as a Series with its own dtype.
The quantity column holds one count or missing entry for each order in the table.
Column selector
A column selector identifies which variables a two-axis selection should return, using labels in loc and positions in iloc.
A mask can choose the rows while ["product", "unit_price"] chooses the columns to display.
Conditional selection
Conditional selection with np.where chooses one output for True entries and another for False entries of a condition.
A price threshold can produce high and low labels without writing a Python loop over rows.
Conditional update
A conditional update assigns new values to cells in rows selected by a condition, typically through one loc assignment.
df.loc[mask, "price"] *= 0.9 discounts exactly the rows selected by the price-update mask.
Copy-on-Write
Copy-on-Write is pandas 3 behavior under which a derived Series or DataFrame acts independently when its values change.
Editing a saved selection of Home orders from an orders table changes that selection while leaving the orders table alone.
Correlation matrix
A correlation matrix records pairwise correlations and is symmetric, with self-correlations of 1 for varying numeric columns.
The rain-temperature entry equals the temperature-rain entry; a constant column instead gives NaN.
CSV
A CSV is a text format for tabular records whose fields are separated by a delimiter, usually commas, often with a header.
A blank field between two delimiters can represent an unrecorded quantity in an order.
Cumulative sum
A cumulative sum is a running total with one accumulated value at each position, returned by the cumsum method.
Daily rainfall cumulative sums track how much rain has accumulated through each day of the week.

D

DataFrame
A DataFrame is a two-dimensional pandas table whose columns share a row index and can each have a different dtype.
An orders table stores product text, numeric quantities and prices in separate columns.
Datetime accessor
The datetime accessor dt provides date and time components or methods for a Series whose values are datetime-like.
After date conversion, .dt.day_name() returns the weekday associated with each order date.
Delimiter
A delimiter is the character separating fields in a text record, specified with sep when pandas reads a CSV file.
A semicolon-delimited file needs sep=";" even if numbers inside its fields use decimal commas.
Dense rank
A dense rank gives consecutive ranks to distinct value groups, so ties do not leave gaps before the next group.
Two tied winners receive rank 1 and the next distinct score receives rank 2 with method dense.
Derived column
A derived column stores values calculated from existing data, such as row-wise arithmetic between two numeric columns.
Multiplying quantity by unit_price creates revenue while keeping each result with its order.
Dictionary mapping
Dictionary mapping translates each input through a key-to-value lookup and makes an unlisted input missing with map.
Mapping every category to a code needs a key for each category whose code should remain known.
Distinct count
A distinct count is the number of different present values in a column, returned by nunique with its default settings.
Six distinct recorded IDs among six rows indicate that the ID column has no repeated values.
dtype
A dtype is the stored type of a Series or column, determining which values it can hold and which operations it supports.
A quantity column may use float64 when one record has a blank quantity read as NaN.
Duplicate record test
A duplicate record test marks repeated rows or repeated values in selected columns, usually leaving the first occurrence unmarked.
In a product column listing Notebook more than once, duplicated(subset="product") marks later Notebook entries even when every order ID differs.

E

Elementwise and
Elementwise and combines masks with &, making a row True only when both corresponding conditions are True.
A Home order costing more than 10 must satisfy both category and price comparisons.
Elementwise or
Elementwise or combines masks with |, making a row True when either corresponding condition, or both, is True.
A selection of Home items or prices above 10 can include expensive items from another category.

F

Filtering
Filtering keeps observations that satisfy a row condition while preserving their values and existing index labels.
After keeping Stationery orders, the original labels can have gaps instead of restarting at zero.
Floating-point error
A floating-point error is a small difference caused by representing and calculating decimal values in binary storage.
A tax calculation can show 1.9000000000000001, which can be rounded to two decimal places.

H

Header
A header is the line containing a table’s column names, which pandas normally reads from the first line of a CSV.
Use header=None when the first line contains an actual record that must remain in the data.

I

iat
The iat indexer selects a single cell by its zero-based row and column positions, without interpreting them as labels.
orders.iat[2, 2] reads the cell in the third row and third column of an orders table.
iloc
The iloc indexer selects rows and columns by zero-based integer positions, independent of their labels or names.
.iloc[-1] returns the last row even if its index label is an order number such as 1006.
Index
An index is the collection of labels attached to a Series or to the rows of a DataFrame, used to identify entries.
A city index lets population["Lima"] request a city’s value without knowing its position.
Index uniqueness
Index uniqueness means that each row label appears only once, allowing a label to serve as an unambiguous row identifier.
Check .index.is_unique before expecting one order ID to return exactly one row.
isin
The isin method makes a membership mask, testing whether each value occurs in a supplied collection of allowed values.
Category membership in ["Home", "Bags"] replaces two equality comparisons joined with or.
isna
The isna method identifies missing entries, producing True for gaps and False for present values in each position.
An isna mask can select the order with no quantity without comparing anything to NaN.

L

Label alignment
Label alignment is the matching of pandas values by index labels during operations, even when their positions differ.
Adding Series indexed in different city orders still combines each city with the same city.
Label slice
A label slice selects a range using start and stop labels and includes both endpoints on a suitable ordered index.
On an index of order labels, .loc[1002:1004] includes the three order labels 1002, 1003 and 1004.
loc
The loc indexer selects rows and columns by labels, accepting individual labels, lists, label slices and boolean masks.
An order-ID index lets .loc[1004, "product"] select the product for one identified order.

M

Mean
The mean is the total of recorded numeric values divided by their count, with pandas skipping missing values by default.
A mean quantity based on five recorded counts must not be divided by all six order rows.
Median
The median is the middle of ordered numeric data, averaging the two middle values when the recorded count is even.
A very wet day can pull weekly mean rain above the median, which stays near the typical dry day.
Minimum rank
A minimum rank gives tied values the smallest occupied rank and leaves gaps for the other places occupied by the tie.
With two values ranked first, the next distinct value gets rank 3 using method min.
Missing-value marker
A missing-value marker is a token or stored value used to indicate that an entry is absent rather than known.
na_values=["-"] tells the CSV reader that a dash in the file represents a missing entry.
Missing-value placement
Missing-value placement specifies where gaps appear in a sorted result, independently of the direction of numeric sorting.
A descending sort still puts NaN last unless na_position="first" is explicitly requested.
Mode
A mode is a value sharing the greatest frequency in a data set; pandas returns a Series because several modes can tie.
If A and B both appear three times and no value appears more often, mode returns both labels.

N

NaN
NaN is a missing-value marker used in floating-point and default pandas 3 text data; it is not a known numeric zero.
A blank quantity can make its calculated revenue missing while known revenues remain usable.
Negative position
A negative position counts backward from the end of an axis, with −1 identifying its last available entry.
The position −2 selects the next-to-last column regardless of that column’s name.
Non-null count
A non-null count is the number of present entries in a column, which can be compared with row count to locate gaps.
Five non-null quantities among six orders mean that one order has no recorded quantity.
Normalized frequency
A normalized frequency is a value’s count divided by the count of all included entries, expressing a proportion.
Three Stationery entries among six present categories give 0.5, or 50% after multiplying by 100.
Nullable integer
A nullable integer dtype stores whole numbers together with missing entries, represented as in pandas Int64.
A count column with a blank can use "Int64" instead of failing conversion to ordinary int.

O

Observation
An observation is the individual case recorded in a row of a tidy table, with its variables recorded in columns.
One row records one order, even when its product also occurs in another order’s row.

P

Pearson correlation
Pearson correlation measures the direction and strength of a linear association between numeric variables on a scale from −1 to 1.
A negative temperature-rain coefficient describes a tendency for warmer days to have less rain.
Percentile rank
A percentile rank expresses a rank as a fraction; default average ranking divides by the number of ranked values.
An average rank of 4.5 among five non-missing values gives a percentile rank of 0.9.
Position slice
A position slice selects a range from an included start position up to, but not including, the stated stop position.
.iloc[1:3] returns positions 1 and 2 and can differ from an inclusive loc slice.
Preview
A preview is a small displayed selection of records used to check visible values and structure before analyzing the full table.
head(3) lets you check the header and the first three records without displaying every row.

Q

Quantile
A quantile marks a position in ordered data for a fraction from zero to one, with pandas interpolating by default.
quantile(0.25) can give a lower quartile between two measured temperatures in a temperature column.
query
The query method filters a DataFrame using a string expression in which column names refer directly to their values.
query("quantity >= 2 and unit_price < 5") can express a combined order filter clearly.
Query variable
A query variable is an outside Python value referenced with an @ prefix so it is distinct from column names.
With limit = 5, query("unit_price > @limit") compares prices against that Python value.

R

Random sample
A random sample is a selection made by a random procedure; a fixed random_state makes the choice repeatable on the same data.
sample(3, random_state=0) is useful when checking rows beyond the beginning or end of a table.
RangeIndex
A RangeIndex is a sequence of integer row labels supplied by default, typically beginning at zero and increasing by one.
After filtering, reset_index(drop=True) replaces retained labels with a new default index.
Rank
A rank is a number describing a value’s place in ordered data, attached to the original row without reordering it.
Descending ranks let each person’s original record carry a place based on their score.
rename
The rename method returns an object with specified labels changed according to a mapping, leaving other labels in place.
rename(columns={"unit_price": "price"}) changes a column’s name without changing its values.
Replacement
Replacement changes specified values while preserving unlisted values, as performed by a Series replace operation.
In a category column of Bags, Home and Stationery, replacing Bags with Luggage leaves the Home and Stationery labels unchanged.
reset_index
The reset_index method returns a table with a new default row index and, unless dropped, the old index kept as a column.
A named order ID index becomes an order_id column again after plain reset_index().
Row-wise apply
Row-wise apply passes each DataFrame row to a function with axis=1, allowing the function to read several columns.
A custom row function can use quantity and price, though column multiplication is faster for revenue.

S

Scalar
A scalar is a single value returned when a selection identifies one cell rather than a Series or DataFrame.
Selecting one unique row label and one column name returns a product name as a scalar.
Scalar assignment
Scalar assignment fills all targeted cells with one supplied value, without needing a separate value for each selected row.
Assigning zero to a loc selection gives every selected cell zero and leaves other rows unchanged.
Series
A Series is a one-dimensional pandas structure that associates each stored value with an index label and has one dtype.
A rain Series can associate readings in millimeters with the labels Mon, Tue and Wed.
set_index
The set_index method returns a table with a chosen column used as row labels, removing that column by default.
orders.set_index("order_id") makes an order number the label used for later row lookups.
Shape
A DataFrame’s shape is a two-item tuple giving its number of rows first and its number of columns second.
A table with six orders and four recorded variables has shape (6, 4) and 24 cells.
Sort key
A sort key is the column or label whose values control order; earlier keys take priority when several are supplied.
Points can be the primary sort key, with names ordering records that share the same points.
Spearman correlation
Spearman correlation measures association through ranks, suiting relationships that consistently increase or decrease.
A steadily increasing curved relationship can be described through ranks without assuming a straight line.
Stable sort
A stable sort preserves the original relative order of entries tied on the sorting value, when requested for one-column sorting.
kind="stable" keeps two equal scores in their previous order instead of imposing a new tie rule.
Standard deviation
Standard deviation measures spread around the mean in the original units; pandas uses the sample denominator by default.
Temperature standard deviation is measured in degrees Celsius, unlike variance in squared degrees.

T

Text accessor
The text accessor str provides vectorized string methods on a text Series, including uppercase conversion and character counts.
orders["product"].str.len() calculates one name length for each recorded product.
Text match
A text match tests a string pattern against each text entry, such as searching inside values with str.contains.
Searching for "note" with case=False matches Notebook even though its N is uppercase.
Top-n selection
A top-n selection retrieves rows with the largest values and can include all boundary ties when keep is set to all.
nlargest(1, "points", keep="all") returns two rows if two people share the highest score.
Type conversion
Type conversion changes values into a chosen dtype so the column supports the operations its meaning requires.
Convert date text before requesting .dt.month, then assign the converted Series back.
Type inference
Type inference is pandas’ choice of a column’s dtype from its input values when no explicit dtype is supplied.
Numeric inference can turn the identifier "001" into 1 unless its dtype is specified as text.

V

Value counts
Value counts report how often each distinct value occurs, usually ordered from most frequent to least frequent.
Category value counts show whether most recorded orders are Stationery, Home or Bags.
Variance
Variance measures the average squared deviation from the mean using the chosen denominator, with ddof=1 by default in pandas.
Matching ddof is necessary before comparing a pandas spread calculation with NumPy defaults.
Vectorized operation
A vectorized operation applies one expression to a whole sequence or column of values without an explicit Python row loop.
Multiplying a price Series by 0.9 reduces each recorded price by the same proportion.

W

Working directory
The working directory is the folder from which Python resolves relative paths when opening files such as a CSV.
A valid filename can still raise FileNotFoundError if Python is running in a different folder.

About this lesson

By StudeliReport a mistake

Make your own Study Materials

Turn your notes, slides and documents into Study Guides, Practice Questions, Flashcards and 6 more tools.

Get Started