Lesson 09
loc and iloc
Select any corner of a DataFrame by label with loc or by position with iloc, and keep the two slicing rules straight in your head.
.loc works in labels: row labels and column names. .iloc works in positions: row numbers and column numbers. Both take a row part and an optional column part, separated by a comma.
One row
Give .loc a row label or .iloc a row number and you get that row as a Series, with the column names as its index. With the default index the label and the position happen to match, so build a labelled index once to see the difference clearly.
import pandas as pd
learners = pd.DataFrame({
"name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
"track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
"city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
"hours": [42, 31, 55, 24, 47, 38],
"score": [88, 74, 91, 65, 82, 79],
})
tagged = learners.set_index("name")
print(tagged.loc["Casey"])
print(tagged.iloc[2])Output:
track Python
city Northgate
hours 55
score 91
Name: Casey, dtype: object
track Python
city Northgate
hours 55
score 91
Name: Casey, dtype: objectRows and columns
After the comma, .loc takes column names and .iloc takes column numbers. A list keeps several, and a single value gives one cell.
import pandas as pd
learners = pd.DataFrame({
"name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
"track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
"city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
"hours": [42, 31, 55, 24, 47, 38],
"score": [88, 74, 91, 65, 82, 79],
})
tagged = learners.set_index("name")
print(tagged.loc["Casey", "score"])
print(tagged.loc["Casey", ["track", "score"]])
print(tagged.iloc[2, 3])
print(tagged.iloc[2, [0, 3]])Output:
91
track Python
score 91
Name: Casey, dtype: object
91
track Python
score 91
Name: Casey, dtype: objectSlices, and the one rule to remember
.loc slices by label and keeps the stop label. .iloc slices by position and drops it, exactly like a list slice. .loc can also slice column names, which is handy for neighbouring columns.
import pandas as pd
learners = pd.DataFrame({
"name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
"track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
"city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
"hours": [42, 31, 55, 24, 47, 38],
"score": [88, 74, 91, 65, 82, 79],
})
tagged = learners.set_index("name")
print(tagged.loc["Jordan":"Riley"])
print(tagged.iloc[1:3])
print(tagged.loc["Avery":"Casey", "track":"hours"])Output:
track city hours score
name
Jordan NumPy Eastport 31 74
Casey Python Northgate 55 91
Riley pandas Westfield 24 65
track city hours score
name
Jordan NumPy Eastport 31 74
Casey Python Northgate 55 91
track city hours
name
Avery Python Northgate 42
Jordan NumPy Eastport 31
Casey Python Northgate 55Whole rows or whole columns
A bare colon means everything on that axis. .iloc[:, 1] is the second column, .loc[:, ['a', 'b']] keeps two columns for every row, and .iloc[[0, 2]] picks scattered rows by number.
import pandas as pd
learners = pd.DataFrame({
"name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
"track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
"city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
"hours": [42, 31, 55, 24, 47, 38],
"score": [88, 74, 91, 65, 82, 79],
})
print(learners.iloc[:, 1])
print(learners.loc[:, ["name", "score"]])
print(learners.iloc[[0, 2, 4]])Output:
0 Python
1 NumPy
2 Python
3 pandas
4 NumPy
5 pandas
Name: track, dtype: object
name score
0 Avery 88
1 Jordan 74
2 Casey 91
3 Riley 65
4 Morgan 82
5 Quinn 79
name track city hours score
0 Avery Python Northgate 42 88
2 Casey Python Northgate 55 91
4 Morgan NumPy Eastport 47 82One cell, quickly
.at and .iat read or write a single cell. They do less checking than .loc, so they are faster in a loop, and they only ever accept one row and one column.
import pandas as pd
learners = pd.DataFrame({
"name": ["Avery", "Jordan", "Casey", "Riley", "Morgan", "Quinn"],
"track": ["Python", "NumPy", "Python", "pandas", "NumPy", "pandas"],
"city": ["Northgate", "Eastport", "Northgate", "Westfield", "Eastport", "Westfield"],
"hours": [42, 31, 55, 24, 47, 38],
"score": [88, 74, 91, 65, 82, 79],
})
tagged = learners.set_index("name")
print(tagged.at["Morgan", "hours"])
print(tagged.iat[4, 2])
tagged.at["Morgan", "hours"] = 50
print(tagged.loc["Morgan"])Output:
47
47
track NumPy
city Eastport
hours 50
score 82
Name: Morgan, dtype: objectKey takeaways
-
.loc takes labels and .iloc takes positions
-
A .loc slice keeps the stop label; an .iloc slice stops one early
-
After the comma come column names for .loc and column numbers for .iloc
-
.at and .iat are the single-cell shortcuts
-
Next: Filtering Rows
-
Previous: Selecting Columns and Rows
Loading playground…
Check your understanding
loc and iloc Quiz
What does .loc select by?
1 / 10