How to print the first 10 rows of a dataframe in Python

Learn to print the first 10 rows of a Python DataFrame. This guide covers methods, tips, real-world applications, and debugging common errors.

How to print the first 10 rows of a dataframe in Python
Published on: 
Tue
Mar 17, 2026
Updated on: 
Tue
Mar 24, 2026
The Replit Team

A quick preview of a pandas DataFrame is a common task in data analysis. The head() method lets you inspect the first few rows to understand your dataset's structure.

In this article, you'll learn several techniques to display the first 10 rows. We'll cover practical tips, explore real-world applications, and offer advice to debug common issues you might face.

Using df.head() to view the first 10 rows

import pandas as pd
# Create a sample dataframe
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
print(df.head(10))--OUTPUT--A   B
0   1  20
1   2  21
2   3  22
3   4  23
4   5  24
5   6  25
6   7  26
7   8  27
8   9  28
9  10  29

This code snippet first constructs a sample DataFrame, df, to work with. The main action happens with df.head(10). While the head() method typically shows the first five rows by default, you can customize this by passing an integer.

Here, we pass 10 to specify that we want to see the first 10 rows. This is a practical way to get a quick, tailored preview of your dataset, helping you verify its structure and check the initial entries without displaying the entire thing.

Basic selection techniques

Beyond the convenience of head(), you can also select the first 10 rows using standard Python slicing or pandas’ powerful integer and label-based indexing.

Using standard Python slicing with [0:10]

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
first_10 = df[0:10]
print(first_10)--OUTPUT--A   B
0   1  20
1   2  21
2   3  22
3   4  23
4   5  24
5   6  25
6   7  26
7   8  27
8   9  28
9  10  29

You can also use standard Python slicing directly on a DataFrame. The expression df[0:10] works just as it would on a list, selecting rows based on their integer position.

  • It grabs all rows starting from index 0 up to, but not including, index 10.

This method is especially intuitive if you're already comfortable with Python's slicing syntax for lists and other sequences.

Using integer-location based indexing with .iloc

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
first_10 = df.iloc[:10]
print(first_10)--OUTPUT--A   B
0   1  20
1   2  21
2   3  22
3   4  23
4   5  24
5   6  25
6   7  26
7   8  27
8   9  28
9  10  29

For more explicit control, you can use the .iloc indexer, which selects data purely by its integer position. The expression df.iloc[:10] grabs all rows from the start up to the tenth position (index 9). This method is often favored for its clarity and predictability.

  • Because .iloc is strictly positional, it prevents potential confusion if your DataFrame's index labels are also numbers but aren't in a simple 0-based sequence.

Using .loc with a boolean condition on index

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
first_10 = df.loc[df.index < 10]
print(first_10)--OUTPUT--A   B
0  1  20
1  2  21
2  3  22
3  4  23
4  5  24
5  6  25
6  7  26
7  8  27
8  9  28

You can also use the .loc indexer, which selects data by its label. Here, you're not slicing by position but filtering with a boolean condition: df.index < 10. This expression checks each index label and returns True for any value less than 10.

  • The .loc indexer then uses these boolean values as a mask.
  • It keeps only the rows where the condition evaluates to True.

This method is powerful for conditional selections, though it relies on the index being numeric for this specific comparison to work as intended.

Advanced techniques

While the basic methods get the job done, pandas also offers more specialized functions for when you need greater flexibility or want to express your logic differently.

Using .query() method for index-based filtering

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
first_10 = df.query('index < 10')
print(first_10)--OUTPUT--A   B
0  1  20
1  2  21
2  3  22
3  4  23
4  5  24
5  6  25
6  7  26
7  8  27
8  9  28

The query() method offers an expressive way to filter data using string expressions. You pass the condition 'index < 10' directly as a string, and pandas evaluates it to select the appropriate rows. This can make your code cleaner and more readable, especially for complex queries.

  • The keyword index inside the string refers directly to the DataFrame's index, allowing you to filter on it.
  • It's a powerful feature that lets you write filtering logic that reads almost like a natural language sentence.

Using .take() method with a range

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
first_10 = df.take(range(10))
print(first_10)--OUTPUT--A   B
0   1  20
1   2  21
2   3  22
3   4  23
4   5  24
5   6  25
6   7  26
7   8  27
8   9  28
9  10  29

The take() method offers a direct way to select rows by their integer positions. It’s designed to work with a list or sequence of indices, which makes it quite flexible for grabbing specific rows from your DataFrame.

  • In this case, range(10) generates the integer positions from 0 to 9.
  • The take() method then fetches the rows that correspond to each of these positions.

This approach is especially useful when you have a specific set of row indices you want to extract, even if they aren't in a consecutive block.

Using .nlargest() with the negative of index column

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
df['neg_idx'] = -df.index
first_10 = df.nlargest(10, 'neg_idx').drop('neg_idx', axis=1)
print(first_10)--OUTPUT--A   B
0   1  20
1   2  21
2   3  22
3   4  23
4   5  24
5   6  25
6   7  26
7   8  27
8   9  28
9  10  29

This approach is a clever, if unconventional, way to get the first 10 rows. It works by temporarily creating a new column, neg_idx, which holds the negative values of the DataFrame's index.

  • The nlargest(10, 'neg_idx') method then finds the 10 "largest" values in this new column. Since the numbers are negative, the largest ones are 0, -1, -2, and so on. This trick effectively selects the rows with the smallest original index values.
  • Finally, drop('neg_idx', axis=1) cleans up by removing the helper column, leaving you with just the first 10 rows.

Move faster with Replit

Replit is an AI-powered development platform that transforms natural language into working applications. Describe what you want to build, and Replit Agent creates it—complete with databases, APIs, and deployment.

The data preview techniques from this article, like using head() or iloc[:10], can be turned into production applications with Replit Agent:

  • Build a data import utility that previews the first 10 rows of an uploaded file to verify its format.
  • Create a dashboard that displays a live feed of the latest entries from a streaming dataset.
  • Deploy a log analysis tool that shows the most recent events from a system log file.

Describe your app idea, and Replit Agent writes the code, tests it, and fixes issues automatically, all in your browser.

Common errors and challenges

Even simple tasks can have tricky spots; here are a few common pitfalls you might encounter when selecting the first few rows.

Forgetting that head() returns 5 rows by default

A frequent slip-up is calling head() without an argument and expecting 10 rows. It’s crucial to remember that the method defaults to showing just five rows. If you need a different number, you must pass it explicitly, as in df.head(10).

Confusing .loc and .iloc indexing methods

It’s easy to mix up pandas' two main indexers, .loc and .iloc, because they seem similar but operate differently. Getting them wrong can lead to unexpected slices of your data or errors.

  • .iloc is strictly for integer-based position. df.iloc[:10] will always grab the first 10 rows, from position 0 to 9.
  • .loc is for label-based indexing. If your index labels are strings or non-sequential numbers, using a slice like df.loc[:'some_label'] depends on the label values, not their position.

Always double-check which one you need—position or label—to avoid bugs.

Misunderstanding string syntax in .query() method

The query() method’s power comes from evaluating string expressions, but that’s also where mistakes happen. You must wrap your entire condition in quotes. For example, writing df.query(index < 10) will fail, while the correct syntax is df.query('index < 10'). The string format is what allows pandas to interpret the command correctly.

Forgetting that head() returns 5 rows by default

It's a classic oversight: you want a quick peek at the first ten rows, so you call the head() method. But without specifying a number, you'll only get five. This common mistake can be misleading if you're expecting a larger sample.

The following code demonstrates what happens when you forget to pass an argument, resulting in a smaller preview than you might have intended.

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
print(df.head())

Since no argument is passed to head(), the method defaults to showing just five rows, which is often not enough for a proper preview. The correct approach provides the specific number of rows you want to see.

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
print(df.head(10))

The fix is simple: always pass an integer to the head() method to specify how many rows you need. By calling df.head(10), you’re explicitly telling pandas to return the first 10 rows, overriding the default behavior. This is crucial when you need a larger sample to verify data loading or get a feel for the dataset's structure. It ensures your initial analysis is based on a sufficient preview, not the smaller default.

Confusing .loc and .iloc indexing methods

Mixing up pandas' main indexers, .loc and .iloc, is a classic stumbling block. While they seem similar, one uses labels and the other uses integer positions. This difference is crucial; getting it wrong can cause your code to fail unexpectedly.

For instance, trying to select columns by name while using the position-based .iloc will raise a TypeError. The following code demonstrates this common mistake, where a string label is incorrectly passed to iloc.

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
first_10_col_A = df.iloc[:10, 'A']
print(first_10_col_A)

The error stems from passing the string label 'A' to .iloc, which strictly requires integer positions for column selection. The following code demonstrates the correct way to achieve this selection without causing a type mismatch.

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
first_10_col_A = df.iloc[:10, 0]
print(first_10_col_A)

The fix is to use the column's integer position instead of its name. Since .iloc is strictly positional, you'll need to provide the column's index. This distinction is key when your code needs to be explicit about data location, preventing errors if column names or labels change.

  • In this case, column 'A' is at position 0, so the correct syntax is df.iloc[:10, 0].

Misunderstanding string syntax in .query() method

The query() method is powerful because it interprets strings, but this flexibility can also cause confusion. It’s common to see redundant code, like referencing the DataFrame's name inside the query string itself. The following code shows an example of this.

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
first_10 = df.query('df.A < 10')
print(first_10)

The query() method operates within the DataFrame's context, so referencing df again inside the string is unnecessary. This redundancy clutters the code and makes it less readable. The correct approach simplifies the expression, as shown below.

import pandas as pd
df = pd.DataFrame({'A': range(1, 20), 'B': range(20, 39)})
first_10 = df.query('A < 10')
print(first_10)

The solution is to write a cleaner expression. Since the query() method works within the DataFrame's context, you can refer to columns directly by name. Simply use the column name in the string, as in df.query('A < 10'), for a more readable approach.

  • This avoids unnecessary repetition and makes your code easier to debug, especially when you're chaining multiple filtering operations.

Real-world applications

Beyond simple data previews, these selection methods are building blocks for advanced operations like per-group analysis and creating representative samples.

Selecting top n rows per group with .groupby() and .head()

You can chain groupby() with head() to perform powerful per-group selections, such as finding the top-selling products within each category.

import pandas as pd

# Create a sample sales dataset
sales_data = pd.DataFrame({
   'category': ['Electronics', 'Clothing', 'Electronics', 'Books', 'Clothing'],
   'product': ['Laptop', 'T-shirt', 'Phone', 'Novel', 'Jeans'],
   'sales': [1200, 50, 800, 30, 80]
})

# Get the top 2 selling products in each category
top_by_category = sales_data.sort_values('sales', ascending=False).groupby('category').head(2)
print(top_by_category)

This technique finds the top two selling products within each category by chaining three methods. It's a common and efficient pattern for ranked, per-group analysis.

  • First, sort_values('sales', ascending=False) arranges all products from highest to lowest sales across the entire dataset.
  • Next, groupby('category') splits the sorted DataFrame into separate buckets for each category.
  • Finally, head(2) is applied to each of these groups, selecting the first two entries—which are the top sellers because of the initial sort.

Creating a sample dataset with .head() and pd.concat()

Combining head() with pd.concat() is a great way to create a sample dataset by pulling the first few rows from multiple sources, like separate yearly sales files.

import pandas as pd

# Simulate data from multiple sources
sales_2020 = pd.DataFrame({
   'product_id': [101, 102, 103, 104, 105],
   'units_sold': [150, 200, 125, 300, 175]
})

sales_2021 = pd.DataFrame({
   'product_id': [101, 103, 106, 107, 108],
   'units_sold': [180, 110, 290, 140, 220]
})

# Create a sample dataset with first 3 rows from each year
sample_data = pd.concat([
   sales_2020.head(3),
   sales_2021.head(3)
])

print(sample_data)

This pattern shows you how to selectively combine pieces from different DataFrames. The code first calls head(3) on both the sales_2020 and sales_2021 DataFrames to isolate the first three rows of each.

  • These two smaller, three-row DataFrames are then put into a list.
  • The list is passed to the pd.concat() function, which stacks them vertically to create a single, new DataFrame. The result is a six-row table that appends the top entries from the second dataset right after the first.

Get started with Replit

Turn these techniques into a real tool. Tell Replit Agent: “Build a CSV uploader that previews the first 10 rows” or “Create a dashboard showing the latest log entries from a file.”

Replit Agent writes the code, tests for errors, and deploys your app from your browser. Start building with Replit.

Get started free

Create and deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.

Get started for free

Create & deploy websites, automations, internal tools, data pipelines and more in any programming language without setup, downloads or extra tools. All in a single cloud workspace with AI built in.