Selecting Columns and Rows
Select single or multiple columns with bracket notation, and retrieve rows by label and position using .loc and .iloc.
Selecting Columns and Rows is a free Pandas & NumPy Academy lesson on CoddyKit — lesson 2 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Pandas & NumPy Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
Selecting a Single Column
Access a single column by name using bracket notation df['col'], which returns a Series. You can also use dot notation df.col when the column name is a valid Python identifier with no spaces. Bracket notation is always safe; dot notation fails for names that clash with DataFrame methods like count or mean.
import pandas as pd
df = pd.DataFrame({'name': ['Alice', 'Bob'], 'score': [90, 75]})
print(df['name']) # Series
print(type(df['name'])) # pandas.core.series.SeriesSelecting Multiple Columns
To select multiple columns, pass a list of column names inside the brackets: df[['col1', 'col2']]. Note the double brackets — the outer pair is the indexing operator, the inner pair creates a Python list. The result is a DataFrame, not a Series. This is commonly used to extract a feature matrix for machine learning.
import pandas as pd
df = pd.DataFrame({'a': [1,2], 'b': [3,4], 'c': [5,6]})
subset = df[['a', 'c']]
print(type(subset)) # pandas.core.frame.DataFrame
print(subset).loc for Row and Column Selection
df.loc[row_label, col_label] selects data by label. Provide a single label, a list of labels, or a slice for both rows and columns. df.loc[:, 'score'] selects all rows of the 'score' column. df.loc['r1':'r3', ['a', 'b']] selects rows r1 to r3 (inclusive) for columns a and b.
import pandas as pd
df = pd.DataFrame({'x': [10,20,30], 'y': [40,50,60]},
index=['r1', 'r2', 'r3'])
print(df.loc['r2', 'x']) # 20
print(df.loc['r1':'r2', 'y']) # r1:40 r2:50.iloc for Positional Selection
df.iloc[row_pos, col_pos] selects by integer position ignoring labels. Both arguments follow Python slice conventions with exclusive stops. df.iloc[:, 0] selects the first column as a Series. df.iloc[0:2, 1:3] selects a rectangular 2×2 sub-DataFrame from the top-left.
import pandas as pd
df = pd.DataFrame({'a': [1,2,3], 'b': [4,5,6], 'c': [7,8,9]})
print(df.iloc[1, 2]) # 8 -- row 1, col 2
print(df.iloc[0:2, 0:2]) # top-left 2x2 sub-tableBoolean Row Selection
Pass a boolean Series (with the same index as the DataFrame) to .loc to filter rows. Build the boolean Series from a column condition. You can combine conditions with & and |. This is the standard filtering pattern in Pandas data analysis and is far more expressive than SQL WHERE clauses for complex multi-column conditions.
import pandas as pd
df = pd.DataFrame({'name': ['A','B','C','D'], 'score': [80,55,92,71]})
high = df.loc[df['score'] >= 70]
print(high)
# name score
# 0 A 80
# 2 C 92
# 3 D 71Compound Filtering Conditions
Multiple conditions must each be in parentheses and combined with & (AND) or | (OR). Using Python's and/or keywords on Series raises an error. To negate a condition, use ~ (tilde) instead of not. Always test conditions individually before combining to isolate the source of unexpected results.
import pandas as pd
df = pd.DataFrame({'name': ['A','B','C','D'],
'score': [80, 55, 92, 71],
'dept': ['Eng', 'HR', 'Eng', 'HR']})
filtered = df.loc[(df['score'] >= 70) & (df['dept'] == 'Eng')]
print(filtered)Selecting Rows by Integer Position
df.iloc[n] returns the n-th row as a Series. df.iloc[n:m] returns rows n through m-1 as a DataFrame. df.iloc[[0, 2, 4]] selects specific rows by position using fancy indexing. These are equivalent to NumPy array row selection and are often used in train/test splitting before applying machine learning models.
import pandas as pd
df = pd.DataFrame({'a': range(5), 'b': range(5, 10)})
print(df.iloc[0]) # first row as Series
print(df.iloc[1:3]) # rows 1 and 2 as DataFrame
print(df.iloc[[0, 4]]) # first and last rowCombining Row and Column Selection
Both .loc and .iloc accept two arguments: df.loc[row_selector, col_selector]. This enables precise rectangular selection in a single expression. A colon : alone selects all rows or all columns. This pattern is essential for extracting a feature matrix with specific columns for only the training rows of a dataset.
import pandas as pd
df = pd.DataFrame({'x': [1,2,3], 'y': [4,5,6], 'z': [7,8,9]})
# Filter rows where x > 1, keep columns y and z
result = df.loc[df['x'] > 1, ['y', 'z']]
print(result)
# y z
# 1 5 8
# 2 6 9Selecting a Single Row with .loc
When you pass a single scalar label to df.loc[label], the result is a Series where the index is the column names. This is useful for inspecting a specific record. To get a single-row DataFrame instead, wrap the label in a list: df.loc[[label]]. The distinction matters when passing results to functions expecting a DataFrame.
import pandas as pd
df = pd.DataFrame({'name': ['A','B'], 'score': [80, 90]},
index=['r1', 'r2'])
print(type(df.loc['r1'])) # Series
print(type(df.loc[['r1']])) # DataFrameat and iat for Fast Scalar Access
df.at[row_label, col_name] and df.iat[row_pos, col_pos] retrieve or set a single scalar value with lower overhead than .loc/.iloc. They are designed for loops that update individual cells. Always prefer vectorized operations over cell-by-cell updates in production code, but use at/iat when you genuinely need to iterate.
import pandas as pd
df = pd.DataFrame({'x': [1, 2, 3], 'y': [4, 5, 6]},
index=['a', 'b', 'c'])
print(df.at['b', 'y']) # 5
print(df.iat[2, 0]) # 3Chained Indexing Warning
Chained indexing like df['col'][condition] or df[mask]['col'] = val can produce a SettingWithCopyWarning because Pandas may operate on a copy instead of the original. Always use a single .loc expression for any modification: df.loc[mask, 'col'] = val. This is the correct, warning-free pattern.
import pandas as pd
df = pd.DataFrame({'score': [80, 55, 92]})
# WRONG - may not modify original:
# df[df['score'] > 60]['score'] = 100
# CORRECT:
df.loc[df['score'] > 60, 'score'] = 100
print(df)Quick Check
Test your understanding of selecting columns and rows from this lesson.
Lesson Recap
In this lesson you learned: .loc selects rows and columns by label with inclusive slice stops, .iloc selects by integer position with exclusive stops like Python slices, and boolean conditions applied through .loc filter rows without the SettingWithCopyWarning pitfall of chained indexing. Next up we add new computed columns, rename existing ones, and remove unwanted columns with drop().
Frequently asked questions
Is the “Selecting Columns and Rows” lesson free?
Yes — the full text of “Selecting Columns and Rows” is free to read here on the web, and the Pandas & NumPy Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Pandas & NumPy Academy course, upgrade to CoddyKit PRO.
What will I learn in “Selecting Columns and Rows”?
Select single or multiple columns with bracket notation, and retrieve rows by label and position using .loc and .iloc. You practise Pandas & NumPy Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Pandas & NumPy Academy?
No prior experience is required. Pandas & NumPy Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 2 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Selecting Columns and Rows” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Pandas & NumPy Academy lesson?
Yes. Every Pandas & NumPy Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Creating DataFrames
- Selecting Columns and Rows
- Adding and Dropping Columns
- Basic DataFrame Inspection