The first look at a data frame — and why it should never be the only look.
What is actually in this file? head is the first thing nearly everyone types after a read_csv or read_excel call, and it does exactly what you would guess: it returns the first five rows. One parameter, n, defaulting to 5. It works on a series too, and asking for more rows than exist returns all of them rather than an error.
That is the entire method. The interesting question is not how head works but what you do with what it shows you, because five rows off the top of a file is a small sample and not a random one. Somebody chose that order. Reading those rows as a description of the data set is the most common way I see an analysis start out wrong.
Official documentation: DataFrame.head and Series.head
The one argument
df.head() # the first 5 rows
df.head(20) # the first 20
df.head(-3) # everything EXCEPT the last 3 rows
s.head(2) # the first 2 values of a series
The third line is the one almost nobody knows about. A negative n means "leave off this many from the end," so head(-3) keeps everything but the final three:
pd.Series([10, 20, 30, 40, 50]).head(-2)
0 10
1 20
2 30
dtype: int64
That is how you drop a "Source: …" footer, a totals row, or the incomplete current month at the end of a time series, without counting the good rows first. tail plays the same trick from the other end.
A worked example, on real data
Here is the Netflix engagement report from Bamboo Weekly #45 — every title the service streamed in the first half of 2023:
import pandas as pd
url = ('https://www.bambooweekly.com/content/files/4cd45et68cgf/1HyknFM84ISQpeua6TjM7A/'
'97a0a393098937a8f29c9d29c48dbfa8/'
'what_we_watched_a_netflix_engagement_report_2023jan-jun.xlsx')
netflix = pd.read_excel(url, header=5,
usecols=['Title', 'Available Globally?',
'Release Date', 'Hours Viewed'])
netflix.head()
Title Available Globally? Release Date Hours Viewed
0 The Night Agent: Season 1 Yes 2023-03-23 812100000
1 Ginny & Georgia: Season 2 Yes 2023-01-05 665100000
2 The Glory: Season 1 // 더 글로리: 시즌 1 Yes 2022-12-30 622800000
3 Wednesday: Season 1 Yes 2022-11-23 507700000
4 Queen Charlotte: A Bridgerton Story Yes 2023-05-04 503000000
English-language hits, released globally, complete release dates, hundreds of millions of hours apiece. Every one of those impressions is wrong, and three more lines say so:
netflix.shape
netflix.dtypes
netflix.isna().sum()
(18214, 4)
Title str
Available Globally? str
Release Date datetime64[us]
Hours Viewed int64
dtype: object
Title 0
Available Globally? 0
Release Date 13359
Hours Viewed 0
dtype: int64
Eighteen thousand rows, not five. Release Date arrived as a real datetime rather than text — worth confirming every time, since a column that comes back as str is a job for astype or pd.to_datetime. And 73 percent of those dates are missing, which the first five rows gave no hint of; dropna is the next stop if that matters to your question.
Then ask for five rows nobody arranged:
netflix.sample(5, random_state=0)
Title Available Globally? Release Date Hours Viewed
3539 The Dragon Prince: Season 1 Yes 2018-09-14 5100000
10964 Miss Butcher // 미스 푸줏간 No NaT 400000
10123 Il principe abusivo No NaT 500000
14385 Yuva // युवा No NaT 200000
6850 A Familiar Stranger: Season 1 // L'Absente: Se... No NaT 1400000
That is the real data set: mostly non-English catalog titles, mostly not available globally, mostly undated, mostly small. The file is sorted by hours viewed, so head was handing me the five biggest rows in it. (random_state is there only so you can reproduce my output.)
Three mistakes people make
Judging a data set from its first five rows. The median title here was watched for 700,000 hours; the median of the five rows head showed me is 622,800,000, nearly a thousand times larger. All five are available globally, while 13,700 of the 18,214 rows are not. Nothing warns you, because a sorted file looks exactly like an unsorted one. head tells you the column names, the dtypes and the shape of a row; .sample(5) tells you what a row usually looks like. Run both.
Expecting groupby(...).head(n) to return the first n groups. It returns the first n rows of every group, stacked back together, so two groups and n=2 give you four rows:
netflix.groupby('Available Globally?').head(2)
Title Available Globally? Release Date Hours Viewed
0 The Night Agent: Season 1 Yes 2023-03-23 812100000
1 Ginny & Georgia: Season 2 Yes 2023-01-05 665100000
6 La Reina del Sur: Season 3 No 2022-12-30 429600000
20 Fake Profile: Season 1 // Perfil falso: Tempor... No 2023-05-31 206500000
Sort first and that is a fine way to get the top n within each group. It is just never what people thought they had asked for.
Assuming you can write to what head returns. netflix.head()['Hours Viewed'] = 0 looks like an edit and is not one. Under Pandas 3's copy-on-write rules you get a ChainedAssignmentError warning rather than an exception, the original data frame is untouched, and the intermediate object you did change is discarded on the next line. If you mean to assign, do it in a single step with .loc[].
Where it shows up in Bamboo Weekly
Bamboo Weekly #45: Netflix is the file above, and the exercise really begins at the moment df.isna().sum() reports 13,359 missing release dates.
Government corruption is head doing the job it is best at. Transparency International's spreadsheet puts two rows of titling above the real column names, so the first read produces nonsense; pd.read_excel(filename, header=2) fixes it, and df.head() is how you confirm the fix at a glance.
Bamboo Weekly #33: Fracking makes the case on a much bigger file: six million records, and df.isna().sum() finds 60,468 missing values concentrated in TotalBaseWaterVolume — the one column every question depends on.
Bamboo Weekly #79: Cyber attacks uses the other head: df['country'].value_counts().head(5) for the five most-affected countries. On a series that is already sorted, that is head at its most honest.
Practice it
Work through a .head() exercise, with instant feedback and no signup required: practice.lernerpython.com/bamboo-weekly/head/
Go deeper
tail is the same method aimed at the bottom of the frame, and needs more care than this one. describe and isna round out the honest first look, sort_values is what makes head mean "the top ten" rather than "the first ten", and value_counts usually answers what people hoped head would.
More Pandas videos on Python and Pandas with Reuven Lerner.
Bamboo Weekly is the practice. If you want the structured version — full courses with downloadable Jupyter notebooks, plus live Pandas office hours when you get stuck — that is LernerPython+Data. A paid Bamboo Weekly subscription is included with it.
Related methods
.nlargest()— when the rows you want are the biggest ones, not simply the first ones.tail()— when the rows worth checking are at the end of the file.describe()— when the first rows are not enough to tell you what the data is.iloc()— when you want a specific position rather than the first n rows
See it on real data
Below are the 69 Bamboo Weekly exercises that use head on real-world data — try each one, then study the worked solution.
- Bamboo Weekly #177: European Summer
- Bamboo Weekly #166: Income tax
- Bamboo Weekly #161: Missiles in Israel
- Bamboo Weekly #159: State of the Union
- Bamboo Weekly #154: University rankings
- Bamboo Weekly #150: Kalshi
- Bamboo Weekly #144: Museum Heists
- Bamboo Weekly #142: Hurricanes
- Bamboo Weekly #140: Stack Overflow survey
- Bamboo Weekly #138: Federal workers
- Bamboo Weekly #130: Jobs reporting
- Bamboo Weekly #129: Tom Lehrer
- Bamboo Weekly #121: Research funding
- Bamboo Weekly #120: Pennies
- Bamboo Weekly #106: Flu season
- Bamboo Weekly #105: Federal employees
- Bamboo Weekly #104: Aviation accidents
- Bamboo Weekly #102: WordPress
- Bamboo Weekly #100: Sports betting
- Bamboo Weekly #97: Drones
- Bamboo Weekly #96: Taylor Swift
- Bamboo Weekly #91: Roller coasters
- Bamboo Weekly #87: Nuclear power
- Bamboo Weekly #86: FEMA
- Bamboo Weekly #83: Gasoline prices
- Bamboo Weekly #81: School
- Bamboo Weekly #80: Inflation
- Bamboo Weekly #79: Cyber attacks
- Bamboo Weekly #77: Paris Olympics
- Bamboo Weekly #76: Aging legislators
- Bamboo Weekly #73: Avocado hand
- Bamboo Weekly #72: City travel
- Bamboo Weekly #69: Election participation
- Bamboo Weekly #65: Microplastics
- Bamboo Weekly #64: Coal power
- Bamboo Weekly #63: Ukraine aid
- Bamboo Weekly #60: Iceland
- Bamboo Weekly #58: NATO
- Bamboo Weekly #51: Academy Awards
- Bamboo Weekly #49: Campaign finance
- Bamboo Weekly #48: Aviation accidents
- Bamboo Weekly #47: Minimum wage
- Bamboo Weekly #45: Netflix
- Bamboo Weekly #43: Financial protection
- Bamboo Weekly #41: Wine production
- Bamboo Weekly #38: Telework
- Bamboo Weekly #35: Terrorism
- Bamboo Weekly #34: House of Representatives
- Bamboo Weekly #33: Fracking
- Bamboo Weekly #32: Unions
- Bamboo Weekly #31: Poverty
- Bamboo Weekly #30: Uncertainty
- Bamboo Weekly #29: Auto accidents
- Bamboo Weekly #28: Pret a Manger
- Bamboo Weekly #27: Young voters
- Bamboo Weekly #26: Hot weather
- Bamboo Weekly #25: Entrepreneurship
- Bamboo Weekly #23: Misery index
- Bamboo Weekly #22: Banana index
- Bamboo Weekly #21: Electric cars
- Bamboo Weekly #18: World population
- Bamboo Weekly #13: Python developers
- Bamboo Weekly #12: Tourism
- Bamboo Weekly #8: Happiness
- Bamboo Weekly #7: Bank failures
- Bamboo Weekly #6: End of the humanities?
- Bamboo Weekly #5: Ukrainian exports
- Bamboo Weekly #3: Earthquake
- Bamboo Weekly #1: Government corruption
Part of the Pandas Methods Index. See also practice by skill.