Mastering Data Selection in Pandas: A Comprehensive Guide to iloc and loc

Pandas is the most popular and widely used Python library for data manipulation and analysis. A critical part of working with data in pandas is selecting subsets of data from DataFrames, which can be done using the loc and iloc indexers. While they are similar in some ways, it‘s important to understand the differences between the two to use them effectively.

In this guide, we‘ll dive deep into the loc and iloc operators, exploring how to leverage them to their full potential for selecting data in pandas DataFrames. We‘ll cover a range of techniques, from basic selection by labels and positions to more advanced concepts like boolean indexing and slicing. By the end of this article, you‘ll have a complete understanding of when and how to use loc and iloc to manipulate your data with ease.

What‘s the Difference Between loc and iloc?

The fundamental difference between pandas‘ loc and iloc indexers is that loc is label-based, while iloc is integer position based. This means that with loc, you select data based on the labels of the rows and columns, i.e. the index and column names. With iloc, you use the integer position of the rows and columns instead, starting from 0.

In practice, this means that loc takes labels as arguments:

df.loc[row_label, column_label] 

While iloc takes integer positions:

df.iloc[row_position, column_position]

To illustrate, let‘s create a sample DataFrame:

data = {
    ‘name‘: [‘John‘, ‘Alice‘, ‘Bob‘],
    ‘age‘: [25, 31, 45], 
    ‘city‘: [‘New York‘, ‘London‘, ‘Paris‘]
}
df = pd.DataFrame(data, index=[‘a‘, ‘b‘, ‘c‘])
   name  age      city
a  John   25  New York
b  Alice  31    London 
c   Bob   45     Paris

With loc, we reference rows and columns by their labels:

df.loc[‘a‘, ‘city‘]  # Select row ‘a‘, column ‘city‘
# ‘New York‘

With iloc, we use integer positions:

df.iloc[0, 2]  # Select row 0, column 2  
# ‘New York‘

Both return the same value, but in different ways. loc used the row label ‘a‘ and column label ‘city‘, while iloc used the integer positions 0 and 2 for the row and column.

Using loc for Label-based Selection

The loc indexer allows you to select data from a DataFrame by labels. You can select single rows or columns, multiple rows or columns, or a combination of both.

Selecting Rows by Label

To select a single row by its label, you can pass the row label to loc:

df.loc[‘a‘]
name        John
age           25
city    New York
Name: a, dtype: object

You can also select multiple rows by passing a list of labels:

df.loc[[‘a‘, ‘c‘]]
   name  age      city
a  John   25  New York
c   Bob   45     Paris

Selecting Columns by Label

Similarly, you can select a single column or multiple columns by passing the column labels:

df.loc[:, ‘age‘] 
a    25
b    31
c    45
Name: age, dtype: int64
df.loc[:, [‘name‘, ‘city‘]]
   name      city
a  John  New York
b  Alice   London
c   Bob     Paris

Here, the : before the comma means to select all rows.

Selecting Rows and Columns Together

You can combine row and column selection by passing both row and column labels to loc:

df.loc[[‘a‘, ‘c‘], [‘name‘, ‘city‘]]
   name      city
a  John  New York 
c   Bob     Paris

Boolean Indexing with loc

Another powerful feature of loc is boolean indexing, where you can pass a boolean Series or array to select rows that meet a certain condition.

For example, to select all rows where the age is greater than 30:

df.loc[df[‘age‘] > 30]
   name  age   city
b  Alice  31  London
c   Bob   45   Paris

You can combine multiple conditions using the & (and) and | (or) operators:

df.loc[(df[‘age‘] > 30) & (df[‘city‘] == ‘Paris‘)]  
  name  age   city
c  Bob   45  Paris

Setting Values with loc

In addition to selecting data, you can also use loc to set values in a DataFrame.

To set a single value:

df.loc[‘a‘, ‘age‘] = 26

To set multiple values:

df.loc[[‘a‘, ‘c‘], ‘city‘] = ‘Tokyo‘

This will update the ‘city‘ for rows ‘a‘ and ‘c‘ to ‘Tokyo‘.

Using iloc for Integer Position based Selection

The iloc indexer allows you select data from a DataFrame by integer position. Like loc, you can select single rows or columns, multiple rows or columns, or a combination of both.

Selecting Rows by Integer Position

To select a single row by its integer position, you can pass the integer to iloc:

df.iloc[0]  
name        John
age           25 
city    New York
Name: a, dtype: object

To select multiple rows, pass a list of integers:

df.iloc[[0, 2]]
   name  age      city
a  John   25  New York
c   Bob   45     Tokyo  

Selecting Columns by Integer Position

You can select columns by passing the integer positions of the columns:

df.iloc[:, 1]
a    25
b    31
c    45 
Name: age, dtype: int64
df.iloc[:, [0, 2]] 
   name      city
a  John  New York
b  Alice   London
c   Bob     Tokyo

Selecting Rows and Columns Together

You can select specific rows and columns by passing lists of integers for both:

df.iloc[[0, 2], [0, 2]]
   name      city 
a  John  New York
c   Bob     Tokyo

Boolean Indexing with iloc

While iloc is primarily used for integer position based selection, you can still use boolean indexing with it by passing a boolean array or Series:

df.iloc[(df[‘age‘] > 30).values]
   name  age   city
b  Alice  31  London  
c   Bob   45   Tokyo

Note that we used .values to convert the boolean Series to a NumPy array, as iloc does not accept boolean Series.

Setting Values with iloc

Like with loc, you can set values using iloc by specifying the integer positions.

To set a single value:

df.iloc[0, 1] = 27

To set multiple values:

df.iloc[[0, 2], 2] = ‘Berlin‘ 

This will update the values in the third column (index 2) for the first and third rows (indices 0 and 2).

Using Negative Integers with iloc

One useful feature of iloc is that it accepts negative integers for indexing. Negative integers count backwards from the end of the axis.

For example, to select the last row:

df.iloc[-1]
name     Bob
age       45
city    Berlin
Name: c, dtype: object 

You can mix positive and negative integers:

df.iloc[[-1, 0]]
   name  age     city
c   Bob   45   Berlin
a  John   27  Berlin

Using Lists or Arrays as Indices

With iloc, you can use lists or NumPy arrays of integers to select data.

rows = np.array([0, 1])
cols = np.array([1, 2]) 
df.iloc[rows, cols]
   age     city
a   27  Berlin  
b   31   London

This can be useful when you have the integer positions stored in variables or coming from some other part of your code.

Slicing with iloc

One of the most powerful features of iloc is slicing. You can pass slice objects to iloc to select ranges of rows or columns.

To select a range of rows:

df.iloc[0:2]  # Selects rows 0 and 1
   name  age     city
a  John   27   Berlin
b  Alice  31   London

To select a range of columns:

df.iloc[:, 1:3]  # Selects columns 1 and 2
   age     city
a   27  Berlin
b   31   London
c   45  Berlin

You can combine row and column slicing:

df.iloc[1:3, 0:2]  # Selects rows 1 and 2, columns 0 and 1
   name  age
b  Alice  31
c   Bob   45

Slicing with iloc is inclusive of the start bound and exclusive of the stop bound, just like regular Python slicing.

Getting Views vs Copies with iloc

One important thing to note about iloc is that it can return either a view or a copy of the data, depending on the types of indices used.

  • If you use only integers, you will get a copy.
  • If you use only slices, you will get a view.
  • If you use a mixture of integers and slices, you will get a copy.

This is important to keep in mind if you plan to modify the returned data. If it‘s a view, any modifications will affect the original DataFrame. If it‘s a copy, modifications will not affect the original DataFrame.

You can use the is_copy attribute to check if the returned data is a view or a copy:

df.iloc[0:2].is_copy  # Returns a view
# None

df.iloc[[0, 2]].is_copy  # Returns a copy  
# True

Summary of Differences Between loc and iloc

Here‘s a summary table comparing the key differences between loc and iloc:

Feature loc iloc
Indexing Label-based Integer position based
Input types Labels (strings, booleans, etc.) Integers
Negative indexing Not allowed Allowed
Slicing Inclusive of both start and stop bounds Inclusive of start bound, exclusive of stop bound
Boolean indexing Allowed Allowed, but requires .values
Setting values Allowed Allowed
Returns views or copies Always returns views Can return views or copies

Conclusion

In this comprehensive guide, we‘ve explored the loc and iloc indexers in pandas, the two primary ways to select data from DataFrames. We‘ve seen how loc is used for label-based selection and iloc for integer position based selection, and we‘ve delved into a variety of techniques for each, including boolean indexing, slicing, and setting values.

Understanding the differences and use cases for loc and iloc is crucial for effective data manipulation in pandas. With the knowledge you‘ve gained from this article, you‘ll be able to confidently select and manipulate data in your DataFrames using these powerful tools.

Remember, the choice between loc and iloc depends on whether you want to select data based on labels or integer positions. If you‘re working with labeled data and want to maintain those labels in your selections, use loc. If you want to select data based on its integer position, regardless of the labels, use iloc.

Happy data wrangling!

How useful was this post?

Click on a star to rate it!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

Similar Posts