Python for Data course menu
pandas loc vs iloc: Selecting Rows and Columns
Select data in pandas with loc (by label) and iloc (by position): single values, rows, columns, slices, lists, combining row and column selection, and how to avoid the SettingWithCopyWarning.
On this page
pandas has two main selectors for DataFrames:
df.loc[rows, columns]selects by label (index values and column names);df.iloc[rows, columns]selects by position (0, 1, 2, …).
Both take the rows first and the columns second, separated by a comma.
import pandas as pd
df = pd.DataFrame({
"dept": ["Sales", "Engineering", "Engineering", "Marketing", "Sales"],
"salary": [52000, 78000, 81000, 46000, 61000],
"city": ["Mumbai", "Bengaluru", "Pune", "Mumbai", "Delhi"],
}, index=["Asha", "Ravi", "Meera", "John", "Priya"])
print(df) dept salary city
Asha Sales 52000 Mumbai
Ravi Engineering 78000 Bengaluru
Meera Engineering 81000 Pune
John Marketing 46000 Mumbai
Priya Sales 61000 DelhiThe examples below use this DataFrame, with names as the index.
loc: by label#
import pandas as pd
df = pd.DataFrame({
"dept": ["Sales", "Engineering", "Engineering", "Marketing", "Sales"],
"salary": [52000, 78000, 81000, 46000, 61000],
"city": ["Mumbai", "Bengaluru", "Pune", "Mumbai", "Delhi"],
}, index=["Asha", "Ravi", "Meera", "John", "Priya"])
print(df.loc["Meera", "salary"]) # one value
print(df.loc["Ravi"]) # one row, as a Series
print(df.loc[["Asha", "Priya"], ["dept", "city"]])
print(df.loc["Ravi":"John", "salary"]) # label slice: end included
print(df.loc[:, "salary":"city"]) # all rows, a range of columns81000
dept Engineering
salary 78000
city Bengaluru
Name: Ravi, dtype: object
dept city
Asha Sales Mumbai
Priya Sales Delhi
Ravi 78000
Meera 81000
John 46000
Name: salary, dtype: int64
salary city
Asha 52000 Mumbai
Ravi 78000 Bengaluru
Meera 81000 Pune
John 46000 Mumbai
Priya 61000 Delhiiloc: by position#
import pandas as pd
df = pd.DataFrame({
"dept": ["Sales", "Engineering", "Engineering", "Marketing", "Sales"],
"salary": [52000, 78000, 81000, 46000, 61000],
"city": ["Mumbai", "Bengaluru", "Pune", "Mumbai", "Delhi"],
}, index=["Asha", "Ravi", "Meera", "John", "Priya"])
print(df.iloc[0]) # first row
print(df.iloc[-1, 1]) # last row, second column
print(df.iloc[1:3, 0:2]) # position slice: end excluded
print(df.iloc[[0, 2, 4], [2]]) # chosen rows, chosen columndept Sales
salary 52000
city Mumbai
Name: Asha, dtype: object
61000
dept salary
Ravi Engineering 78000
Meera Engineering 81000
city
Asha Mumbai
Meera Pune
Priya DelhiSelecting with conditions#
loc also accepts a boolean Series for the rows. This is the standard way to filter and pick columns in one step (more in Filtering Rows):
import pandas as pd
df = pd.DataFrame({
"dept": ["Sales", "Engineering", "Engineering", "Marketing", "Sales"],
"salary": [52000, 78000, 81000, 46000, 61000],
}, index=["Asha", "Ravi", "Meera", "John", "Priya"])
print(df.loc[df["salary"] > 60000, "dept"])Ravi Engineering
Meera Engineering
Priya Sales
Name: dept, dtype: objectChanging values safely#
Use loc with both the rows and the column in one call to set values:
import pandas as pd
df = pd.DataFrame({
"dept": ["Sales", "Engineering", "Marketing"],
"salary": [52000, 78000, 46000],
}, index=["Asha", "Ravi", "John"])
df.loc[df["dept"] == "Sales", "salary"] += 5000 # raise for Sales only
df.loc["John", "dept"] = "Growth"
print(df) dept salary
Asha Sales 57000
Ravi Engineering 78000
John Growth 46000Writing df[df["dept"] == "Sales"]["salary"] = ... (two separate brackets) is chained assignment: the first step may create a copy, so the change is lost and pandas warns with SettingWithCopyWarning. One loc call with rows and column avoids the problem.
Fast single values: at and iat#
For reading or writing one value in a loop, at (label) and iat (position) are faster than loc/iloc:
import pandas as pd
df = pd.DataFrame({"salary": [52000, 78000]}, index=["Asha", "Ravi"])
print(df.at["Ravi", "salary"], df.iat[0, 0])78000 52000Common mistakes#
Practice#
Practice exercise
Using the employees DataFrame from this lesson (names as the index), print: (1) Priya's city, (2) the first three rows with only the salary column, (3) the departments of everyone in Mumbai, and (4) the DataFrame after giving everyone in Engineering a salary of at least 80000 (use .clip(lower=80000) on their salaries).
Show hint
(1) loc["Priya", "city"]; (2) iloc[:3] and the column position, or loc with .index[:3]; (3) a boolean condition in loc; (4) df.loc[cond, "salary"] = df.loc[cond, "salary"].clip(lower=80000).
Show solution
import pandas as pd
df = pd.DataFrame({
"dept": ["Sales", "Engineering", "Engineering", "Marketing", "Sales"],
"salary": [52000, 78000, 81000, 46000, 61000],
"city": ["Mumbai", "Bengaluru", "Pune", "Mumbai", "Delhi"],
}, index=["Asha", "Ravi", "Meera", "John", "Priya"])
print(df.loc["Priya", "city"])
print(df.iloc[:3, 1])
print(df.loc[df["city"] == "Mumbai", "dept"])
eng = df["dept"] == "Engineering"
df.loc[eng, "salary"] = df.loc[eng, "salary"].clip(lower=80000)
print(df)Delhi
Asha 52000
Ravi 78000
Meera 81000
Name: salary, dtype: int64
Asha Sales
John Marketing
Name: dept, dtype: object
dept salary city
Asha Sales 52000 Mumbai
Ravi Engineering 80000 Bengaluru
Meera Engineering 81000 Pune
John Marketing 46000 Mumbai
Priya Sales 61000 DelhiRavi's salary rose to 80000; Meera already earned more, so clip left her unchanged.
Key takeaway#
Next: Filtering Rows.
Finished this lesson?