DataLens

Selecting columns and rows

Pick the columns you need, slice rows by position, and understand when you get a Series back versus a DataFrame.

Level: Foundations · 8 min read

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

The idea

A dataset usually has more columns and rows than any one question needs. Selecting just what you need makes output readable, calculations faster, and code clearer about what it actually uses. This module covers the everyday selections; the next two add filtering by condition and the precise loc/iloc tools.

import pandas as pd

sales = pd.read_csv("sales.csv")

One column: a Series

Square brackets with a single column name give you that column as a Series:

revenue = sales["revenue"]
print(type(revenue).__name__)
print(revenue.head(3))
print(revenue.sum())
Series
0     89000
1    285000
2    960000
Name: revenue, dtype: int64
17502000

You may also see sales.revenue (attribute style). It works for simple names, but breaks for names with spaces, names that clash with methods (a column called count or size), and new columns. Stick to sales["revenue"]: it always works.

Several columns: a DataFrame

Most reports need a few columns, not one. Say you want to see who bought what and for how much: that's the customer, product and revenue columns. Pass a list of column names inside the brackets, which is why you see double brackets:

lines = sales[["customer", "product", "revenue"]]
print(type(lines).__name__)
print(lines.head(3))
DataFrame
        customer            product  revenue
0  Kartika Rahma     Desk Organizer    89000
1     Citra Dewi  Arabica Gayo 250g   285000
2      Eka Putri   Pour-over Kettle   960000

The outer brackets select; the inner brackets are the list. The columns come back in the order you list them, so this is also how you reorder columns.

Key idea

df["col"] gives a Series; df[["col"]] (a list with one name) gives a DataFrame with one column. Many "why doesn't this method work" puzzles come down to which one you have.

Dropping columns you don't want

When you want almost every column, listing them all is tedious. If you only want to get rid of a couple, it's easier to say what to remove:

slim = sales.drop(columns=["segment", "channel"])
print(slim.shape)
print(sales.shape)
(71, 10)
(71, 12)

.drop() returns a new DataFrame; sales is unchanged. Most pandas methods work this way, which keeps your original data safe. You'll meet more column operations in module 7.

Rows by position: slicing

Slicing with : inside the brackets selects rows by position, exactly like a list:

print(sales[["customer", "product"]][10:13])
        customer               product
10  Lukman Hakim          Throw Pillow
11  Lukman Hakim  Robusta Lampung 250g
12  Lukman Hakim    Notebook A5 Dotted

Rows 10, 11 and 12: start included, stop excluded. .head(n) and .tail(n) are the readable shortcuts for the first and last rows.

The square-bracket rules are a little overloaded: a string or list selects columns, a slice selects rows. That's convenient for quick work, but it's also why the next modules introduce .loc and .iloc, which are always explicit.

Picking one value

To get a single value, select the column, then the row label:

print(sales["product"][2])
print(sales.loc[2, "product"])
Pour-over Kettle
Pour-over Kettle

Both work; .loc[row, column] is the cleaner, one-step form, and it's what you should use (module 6 explains why).

Selecting columns by type or name pattern

For wide tables, select columns by a rule rather than typing every name:

numbers = sales.select_dtypes(include="number")
print(list(numbers.columns))

price_cols = [col for col in sales.columns if "price" in col or col == "revenue"]
print(price_cols)
['order_id', 'quantity', 'unit_price', 'revenue']
['unit_price', 'revenue']

select_dtypes picks columns by type ("number", "object", "datetime"), and a plain list comprehension over df.columns handles any naming rule you can express in Python.

Sorting the columns for a report

Combining what you know: select, reorder, and show the most important rows.

report_cols = ["order_id", "order_date", "customer", "revenue"]
print(sales[report_cols].head(4).to_string(index=False))
 order_id order_date      customer  revenue
        1 2024-01-03 Kartika Rahma    89000
        2 2024-01-09    Citra Dewi   285000
        3 2024-01-17     Eka Putri   960000
        4 2024-01-18    Citra Dewi    75000

.to_string(index=False) prints without the row labels, handy for clean text output. Keeping the column list in a named variable (report_cols) documents what the report contains and makes it easy to change.

Why this matters for clean code

Select early and explicitly. A function that only needs three columns should take or create a three-column frame, so a reader sees exactly what data it depends on, and changes to other columns can't break it. Name your column lists (ID_COLUMNS, report_cols), prefer df["col"] over attribute access, and remember that methods like .drop() return new frames rather than changing the original.

Recap

Practise this module

The questions for this lesson run in your browser and check your answer straight away.

Next: Filtering with boolean masks →