On this page
Most students learn that loc uses labels and iloc uses positions, then get caught when the labels are themselves numbers. That happens all the time in Class 12 Informatics Practices, because a DataFrame made from lists or Series gets the labels 0, 1, 2 by default. This post works through that case with real output, explains the two error messages, and shows how loc adds and changes rows.
What does the syllabus and textbook cover?
The CBSE Informatics Practices (065) curriculum for 2026-27 lists, for DataFrames, "Operations on rows and columns: add, select, delete, rename" and "Indexing using Labels, Boolean Indexing". NCERT's Class 12 IP chapter on Pandas teaches label-based indexing with DataFrame.loc[ ], Boolean indexing, and adding or changing a row with loc. It does not use iloc. The pandas documentation covers both, so iloc is worth knowing for your practical work and project, but write label-based answers where the question asks for them.
Our earlier post on Pandas Series and DataFrames covers building DataFrames and the basic loc and iloc slice. This one goes further.
What exactly do loc and iloc do?
The pandas indexing guide is the reference:
.loc is primarily label based. It raises KeyError when a label is not found. In a label slice, both the start and the stop are included. A number inside loc is read as a label, not a position.
.iloc is primarily integer-position based, from 0 to length − 1. A slice includes the start and excludes the stop, as in ordinary Python. It raises IndexError for a single out-of-range position, but a slice may run past the end.
NCERT makes the same point about numbers in loc: when the row label is passed as an integer, it is interpreted as a label of the index and not as a position.
Worked example: when labels are numbers
Here is a small shop DataFrame. The output below was produced by running the code with pandas 2.3.3.
import pandas as pd
df = pd.DataFrame({'Item': ['Bread', 'Milk', 'Eggs', 'Rice', 'Dal'],
'Qty': [50, 100, 120, 30, 45],
'Price': [30, 25, 6, 60, 110]})
df = df.drop(1)
print(df) Item Qty Price
0 Bread 50 30
2 Eggs 120 6
3 Rice 30 60
4 Dal 45 110Dropping Milk removed the label 1. The labels are now 0, 2, 3, 4, but the positions are still 0, 1, 2, 3. Predict before reading on.
print(df.loc[2:4])
print(df.iloc[2:4]) Item Qty Price
2 Eggs 120 6
3 Rice 30 60
4 Dal 45 110
Item Qty Price
3 Rice 30 60
4 Dal 45 110loc[2:4] means labels 2 to 4 inclusive: three rows. iloc[2:4] means positions 2 and 3 (the stop is excluded): Rice and Dal, which carry labels 3 and 4.
Single cells follow the same rule. df.loc[3, 'Qty'] gives 30 (label 3 is Rice). df.iloc[1, 1] gives 120 (position 1 is Eggs, column position 1 is Qty).
Why does one give KeyError and the other IndexError?
df.loc[1] # KeyError: 1 (label 1 was dropped)
df.iloc[4] # IndexError: single positional indexer is out-of-bounds
df.iloc[2:10] # no error: returns Rice and DalLabel 1 no longer exists, so loc fails with KeyError. There are only four rows, so position 4 does not exist and iloc raises IndexError. But the slice 2:10 is allowed to run past the end, exactly as the pandas guide says, and just returns the rows that exist.
How do you filter, update and add rows with loc?
loc takes a Boolean condition for rows and a list of columns:
print(df.loc[df['Price'] > 40, ['Item', 'Price']])This returns Rice (60) and Dal (110).
You can also assign through loc. This line sets every quantity below 40 to 40, so Rice's 30 becomes 40:
df.loc[df['Qty'] < 40, 'Qty'] = 40Assigning to a label that does not exist adds a row. The pandas guide calls this setting with enlargement, and NCERT uses it to add a row. The 2026-27 IP sample paper asks you to add [Butter, 40, 55] to a DataFrame with labels 0 to 2, and the marking scheme answer is StoreDF.loc[3] = ['Butter', 40, 55]. If the label already exists, the same line overwrites that row instead.
One more note: NCERT's chapter also shows DataFrame.append() for joining DataFrames. The pandas 2.0 release notes record that append() was removed, with concat() as the replacement, so that code fails on current pandas.
Which slips cost the most marks?
Reading a number in loc as a position. It is a label.
Making a loc slice stop early. Label slices include the stop.
Expecting an error from an over-long iloc slice. Slices are allowed past the end; single positions are not.
Forgetting the brackets for two columns. Use ['Item', 'Price'].
Using df.loc[3] = ... to add a row when label 3 already exists. It replaces that row.
A practice routine for indexing
Daily, 15 minutes: build a five-row DataFrame, drop one row, and predict three loc and three iloc outputs before running them.
Twice a week: write two lines that should raise KeyError and IndexError, run them, and copy the messages into your notes.
Weekly: rewrite one sample paper answer, then change the labels and check whether it still works.
When an output surprises you and you cannot see why, the Fermi Problem Library has a step-by-step solver that explains the reasoning rather than printing an answer.
Tonight, run the shop example above, then change df.drop(1) to df.drop(3) and predict the new loc[2:4] and iloc[2:4].



