Difficulty: Beginner
Selecting specific rows, columns, or subsets of data is the most fundamental operation you will perform with Pandas. The library provides multiple ways to access data, and understanding the differences between them is critical for writing correct and efficient code. The two primary indexing methods are loc (label-based) and iloc (integer position-based), and mastering both is essential.
The loc accessor selects data by label. You use it with row labels (index values) and column names. The syntax is df.loc[row_label, column_name] for a single value, df.loc[row_label] for an entire row, or df.loc[:, column_name] for an entire column. When slicing with loc, both the start and stop values are inclusive, which differs from standard Python slicing where the stop is exclusive. For example, df.loc[0:2] includes rows with labels 0, 1, and 2.
The iloc accessor selects data by integer position, just like Python list indexing. The syntax mirrors loc, but you use integer positions instead of labels: df.iloc[0] for the first row, df.iloc[:, 1] for the second column, df.iloc[0:2] for the first two rows (stop is exclusive, matching Python convention). iloc is useful when you do not know or care about the labels and just want to access data by its position in the DataFrame.
Column selection is simpler. You can select a single column with df['column_name'] (returns a Series) or df[['col1', 'col2']] (returns a DataFrame with multiple columns). The double bracket syntax is necessary for multiple columns because you are passing a list of column names. You can also use dot notation (df.column_name) for single columns, but this does not work if the column name contains spaces, conflicts with a DataFrame method name, or if you want to assign values.
Boolean filtering (also called conditional indexing or boolean masking) lets you select rows based on conditions. The expression df[df['Age'] > 30] first evaluates df['Age'] > 30, which produces a boolean Series with True/False for each row. This boolean Series is then used to filter the DataFrame, keeping only rows where the condition is True. You can combine conditions using & (and), | (or), and ~ (not), but each condition must be wrapped in parentheses: df[(df['Age'] > 25) & (df['City'] == 'Mumbai')]. This is one of the most powerful and frequently used features in Pandas.
import pandas as pd
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Age': [25, 30, 35, 28],
'City': ['Delhi', 'Mumbai', 'Pune', 'Delhi']
})
# Select a single value
print("Name at row 1:", df.loc[1, 'Name'])
# Select a row
print("---")
print(df.loc[2])
# Select rows 0 to 2, columns Name and City
print("---")
print(df.loc[0:2, ['Name', 'City']])
loc uses label-based indexing. df.loc[1, 'Name'] gets the value at row label 1, column 'Name'. df.loc[2] returns the entire row as a Series. The slice 0:2 with loc is inclusive on both ends, so it returns rows 0, 1, and 2.
import pandas as pd
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie', 'Diana'],
'Age': [25, 30, 35, 28],
'City': ['Delhi', 'Mumbai', 'Pune', 'Delhi']
})
# First row
print("First row:")
print(df.iloc[0])
# Last two rows, first two columns
print("---")
print(df.iloc[-2:, :2])
iloc uses integer positions like Python lists. df.iloc[0] gets the first row. df.iloc[-2:, :2] gets the last 2 rows and the first 2 columns. Unlike loc, iloc slicing is exclusive on the stop end.
import pandas as pd
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie', 'Diana', 'Eve'],
'Age': [25, 30, 35, 28, 32],
'Salary': [50000, 60000, 70000, 55000, 65000]
})
# Filter rows where Age > 29
print("Age > 29:")
print(df[df['Age'] > 29])
# Combine conditions
print("---")
print("Age > 25 AND Salary >= 60000:")
print(df[(df['Age'] > 25) & (df['Salary'] >= 60000)])
df['Age'] > 29 creates a boolean Series. Passing it inside df[...] filters rows where the condition is True. Use & for AND and | for OR, with parentheses around each condition.
import pandas as pd
df = pd.DataFrame({
'Name': ['Alice', 'Bob', 'Charlie'],
'Age': [25, 30, 35],
'City': ['Delhi', 'Mumbai', 'Pune'],
'Salary': [50000, 60000, 70000]
})
# Single column (returns Series)
print("Single column type:", type(df['Name']).__name__)
# Multiple columns (returns DataFrame)
subset = df[['Name', 'Salary']]
print("---")
print(subset)
Single bracket with a string returns a Series. Double brackets with a list of strings returns a DataFrame. This distinction matters when chaining operations, as some methods work differently on Series vs DataFrame.
loc, iloc, Column Selection, Boolean Filtering, Conditional Indexing