Use head() to preview the first rows in the current order. Check imported data quickly, then inspect the full table before calculating totals or exporting records.
head() returns rows by position in the current order. It does not sort, sample randomly or check the whole dataset.
import pandas as pd
from io import StringIO, BytesIO
students = pd.DataFrame({
"NAME": ["Ravi", "Raju", "Alex", "Ron", "King", "Jack"],
"ID": [1, 2, 3, 4, 5, 6],
"MATH": [80, 40, 70, 70, 70, 30],
"ENGLISH": [80, 70, 40, 50, 60, 30]
})
print(students)Expected output
NAME ID MATH ENGLISH
0 Ravi 1 80 80
1 Raju 2 40 70
2 Alex 3 70 40
3 Ron 4 70 50
4 King 5 70 60
5 Jack 6 30 30The default is n=5. The result retains all columns and existing row labels. Fewer than five available rows produces the entire table.
print(students.head())
assert students.head()["ID"].tolist() == [1, 2, 3, 4, 5]Expected output
NAME ID MATH ENGLISH
0 Ravi 1 80 80
1 Raju 2 40 70
2 Alex 3 70 40
3 Ron 4 70 50
4 King 5 70 60Pass an integer to choose how many initial rows to return. A DataFrame caller returns a DataFrame; a Series caller returns a Series.
print(students.head(2))
print("Series preview:")
print(students["NAME"].head(2))
assert students.head(2)["NAME"].tolist() == ["Ravi", "Raju"]Expected output
NAME ID MATH ENGLISH
0 Ravi 1 80 80
1 Raju 2 40 70
Series preview:
0 Ravi
1 Raju
Name: NAME, dtype: strhead(0) gives an empty table with the same columns. An oversized positive count returns all available rows. A negative count excludes that many rows from the end; it does not return the last rows.
for n in [0, 20, -2, -20]:
preview = students.head(n)
print("n:", n, "Rows:", len(preview), "IDs:", preview["ID"].tolist())
assert students.head(-2)["ID"].tolist() == [1, 2, 3, 4]
assert students.head(0).columns.equals(students.columns)Expected output
n: 0 Rows: 0 IDs: []
n: 20 Rows: 6 IDs: [1, 2, 3, 4, 5, 6]
n: -2 Rows: 4 IDs: [1, 2, 3, 4]
n: -20 Rows: 0 IDs: []A named or nonsequential index does not change which rows head() selects. iloc is an indexer with square brackets and offers explicit positional slicing.
indexed = students.set_index("ID")
print(indexed.head(2))
print("Same as positional slice:", indexed.head(2).equals(indexed.iloc[:2]))
assert indexed.head(2).equals(indexed.iloc[:2])Expected output
NAME MATH ENGLISH
ID
1 Ravi 80 80
2 Raju 40 70
Same as positional slice: TrueSelect meaningful columns before displaying a wide table. Use columns and info() for full structural inspection.
preview = students.loc[:, ["ID", "NAME", "MATH"]].head(3)
print(preview)
assert preview.shape == (3, 3)Expected output
ID NAME MATH
0 1 Ravi 80
1 2 Raju 40
2 3 Alex 70This embedded CSV makes the example runnable without an upload. For your file, replace StringIO(csv_text) with a file path or URL. For Windows paths use a raw string, such as r"D:\my_data\student.csv". See read_csv().
csv_text = students.to_csv(index=False)
from_csv = pd.read_csv(StringIO(csv_text))
print(from_csv.head(2))
print("Full shape:", from_csv.shape)
assert from_csv.shape == (6, 4)Expected output
NAME ID MATH ENGLISH
0 Ravi 1 80 80
1 Raju 2 40 70
Full shape: (6, 4)An in-memory workbook demonstrates the same read_excel() and index_col options without a local student.xlsx file. Excel requires an engine such as openpyxl; this cell explains a missing dependency rather than requiring installation to run the notebook. See read_excel() and to_excel().
try:
import openpyxl
except ImportError:
print("Excel example requires openpyxl; continue with the CSV examples.")
else:
workbook = BytesIO()
students.rename(columns={"ID": "id"}).to_excel(workbook, index=False, engine="openpyxl")
workbook.seek(0)
from_excel = pd.read_excel(workbook, index_col="id", engine="openpyxl")
print(from_excel.head(3))
print("Full shape:", from_excel.shape)
assert from_excel.shape == (6, 3)
assert from_excel.index.tolist() == [1, 2, 3, 4, 5, 6]Expected output
NAME MATH ENGLISH
id
1 Ravi 80 80
2 Raju 40 70
3 Alex 70 40
Full shape: (6, 3)Reading a full CSV and then calling head() still loads the full file. read_csv(nrows=...) limits rows read for a small inspection. That limited table cannot support full-file counts or totals.
limited = pd.read_csv(StringIO(csv_text), nrows=2)
print(limited)
print("Loaded rows:", len(limited))
assert len(limited) == 2Expected output
NAME ID MATH ENGLISH
0 Ravi 1 80 80
1 Raju 2 40 70
Loaded rows: 2shape is an attribute and returns a tuple of rows and columns. to_string() formats the preview. Count rows from the full table, not from head().
summary = "Rows:" + str(students.shape[0]) + ",Columns:" + str(students.shape[1])
summary = summary + "\n" + students.head(2).to_string()
print(summary)
assert summary.startswith("Rows:6,Columns:4")Expected output
Rows:6,Columns:4
NAME ID MATH ENGLISH
0 Ravi 1 80 80
1 Raju 2 40 70head() alone does not find the highest values. Define sorting and ties first, or use nlargest(). Here ID is the tie-breaker. See sort_values().
top = students.sort_values(["MATH", "ID"], ascending=[False, True]).head(3)
print(top)
assert top["ID"].tolist() == [1, 3, 4]Expected output
NAME ID MATH ENGLISH
0 Ravi 1 80 80
2 Alex 3 70 40
3 Ron 4 70 50tail() shows the end. sample() selects random rows; random_state makes this small demonstration reproducible. Neither a first-row preview nor a random sample proves the whole dataset is valid.
print("First IDs:", students.head(2)["ID"].tolist())
print("Last IDs:", students.tail(2)["ID"].tolist())
sample = students.sample(n=2, random_state=42)
print("Sample IDs:", sample["ID"].tolist())
assert len(sample) == 2Expected output
First IDs: [1, 2]
Last IDs: [5, 6]
Sample IDs: [1, 2]This synthetic sales CSV places an invalid amount after the initial rows. Preserve IDs as text to retain leading zeros. A clean-looking preview is a starting point; inspect all rows before reporting revenue. Continue with Data Cleaning.
sales_csv = "order_id,product,amount\n001,Pen,5\n002,Book,20\n003,Notebook,15\n004,Bag,bad\n005,Pencil,\n006,Pen,7\n"
sales = pd.read_csv(StringIO(sales_csv), dtype={"order_id": "string"})
print("Initial preview:")
print(sales.head(3))
amount = pd.to_numeric(sales["amount"], errors="coerce")
review = sales.loc[amount.isna()].copy()
print("Review rows from the full table:")
print(review)
assert review["order_id"].tolist() == ["004", "005"]Expected output
Initial preview:
order_id product amount
0 001 Pen 5
1 002 Book 20
2 003 Notebook 15
Review rows from the full table:
order_id product amount
3 004 Bag bad
4 005 Pencil NaNKnown amounts total 47 across four accepted orders. Missing or invalid amounts remain in review rather than becoming zero. Use sum() and count() under an explicit missing-value policy.
accepted = sales.loc[amount.notna()].copy()
accepted["amount"] = amount.loc[accepted.index]
print("Source rows:", len(sales))
print("Accepted:", len(accepted), "Review:", len(review))
print("Known revenue:", accepted["amount"].sum())
print("Accepted preview:")
print(accepted.head(2))
assert len(accepted) + len(review) == len(sales)
assert accepted["amount"].sum() == 47Expected output
Source rows: 6
Accepted: 4 Review: 2
Known revenue: 47.0
Accepted preview:
order_id product amount
0 001 Pen 5.0
1 002 Book 20.0Export accepted rather than accepted.head(2) when you need every accepted order. An explicitly named preview export can be useful, but its totals describe only those rows. See Input and Output.
print(accepted.to_csv(index=False).rstrip())
print("Export rows:", len(accepted))
assert len(accepted) == 4
# Optional Colab export:
# accepted.to_csv("accepted_sales.csv", index=False)Expected output
order_id,product,amount
001,Pen,5.0
002,Book,20.0
003,Notebook,15.0
006,Pen,7.0
Export rows: 4Does head() change the original? No. Why are fewer rows returned? The table may contain fewer than n rows. Why are old row labels visible? head() preserves the index; use reset_index() deliberately. Why are columns truncated on screen? Display settings control formatting; select columns or use to_string() for a small preview. Is this a random sample? No; it follows current order. Does it validate every row? No. Continue with describe(), shape and size, text-match counts and student exercises.
Create four orders with statuses paid, test, paid, paid and amounts 10, 99, 20, 30. Keep paid orders, preview the first two, and calculate revenue from all paid orders. Predict both row counts and revenue.
There are three paid orders; the preview has two rows. Full paid revenue is 60, while preview revenue is 30.
practice = pd.DataFrame({"status": ["paid", "test", "paid", "paid"], "amount": [10, 99, 20, 30]})
paid = practice.loc[practice["status"].eq("paid")]
preview = paid.head(2)
print(preview)
print("Paid orders:", len(paid), "Preview rows:", len(preview))
print("Full paid revenue:", paid["amount"].sum())
assert len(paid) == 3 and len(preview) == 2
assert paid["amount"].sum() == 60Expected output
status amount
0 paid 10
2 paid 20
Paid orders: 3 Preview rows: 2
Full paid revenue: 60Open in Google Colab View on GitHub
Run the examples in order, change preview sizes and sales values, then compare preview rows with full-table checks. Save your own copy to keep edits. All sample tables are included in the notebook.
Continue with the Data Cleaning hub, where(), loc, at, NumPy where(), fillna() and iloc.
Reference: Pandas DataFrame.head documentation.
Author & Instructor at plus2net
I write and maintain practical tutorials on Python, PHP, SQL, JavaScript, HTML, jQuery, and web development at plus2net. The tutorials focus on clear explanations, working examples, and code that readers can test and adapt while learning.