The DataFrame: Rows and Columns

Reviewed & published by Brayan K

A DataFrame is a two-dimensional, table-like structure of labelled rows and columns — Pandas' core object, where every column is itself a Series and all columns share one common row index.

Part of the free Pandas course at LearnCodingFast — hands-on lessons with examples you run in your browser, plus practice exercises and a quick quiz.

If the Series is a single column, the DataFrame is the whole spreadsheet. This is the object you'll spend 95% of your Pandas time working with.

What You'll Learn in This Lesson

1 What Is a DataFrame?

A DataFrame is a 2-dimensional table of data: it has labelled rows (the index) and labelled columns.

Build one from a dictionary of lists: keys are column names, each list is a column's values.

data = {
    "name": ["Alice", "Bob", "Carol"],
    "age": [25, 30, 35],
}
df = pd.DataFrame(data)
import pandas as pd

data = {
    "name": ["Alice", "Bob", "Carol"],
    "age": [25, 30, 35],
    "city": ["London", "Paris", "Berlin"],
}

df = pd.DataFrame(data)
print(df)

# Output:
#     name  age    city
# 0  Alice   25  London
# 1    Bob   30   Paris
# 2  Carol   35  Berlin

# ✅ Expected output:
#     name  age    city
# 0  Alice   25  London
# 1    Bob   30   Paris
# 2  Carol   35  Berlin

2 Inspecting the Structure

Four attributes tell you everything about a DataFrame's shape and structure:

import pandas as pd

df = pd.DataFrame({
    "name": ["Alice", "Bob", "Carol"],
    "age": [25, 30, 35],
    "city": ["London", "Paris", "Berlin"],
})

print(df.shape)      # (rows, columns)
print(df.columns)    # column names
print(df.index)      # row labels
print(df.dtypes)     # type of each column

# Output:
# (3, 3)
# Index(['name', 'age', 'city'], dtype='object')
# RangeIndex(start=0, stop=3, step=1)
# name    object
# age      int64
# city    object
# dtype: object

# ✅ Expected output:
# (3, 3)
# Index(['name', 'age', 'city'], dtype='object')
# RangeIndex(start=0, stop=3, step=1)
# name    object
# age      int64
# city    object
# dtype: object

3 Selecting a Column Returns a Series

Grab a single column with square brackets and the column name. The result is a Series — exactly the object from the Series lesson:

ages = df["age"]
type(ages)   # <class 'pandas.core.series.Series'>

Because it's a Series, every Series trick still works: df["age"].mean(), df["age"] * 2, boolean filtering, and more.

import pandas as pd

df = pd.DataFrame({
    "name": ["Alice", "Bob", "Carol"],
    "age": [25, 30, 35],
})

ages = df["age"]      # selecting one column returns a Series
print(ages)
print(type(ages))
print("Average age:", ages.mean())

# Output:
# 0    25
# 1    30
# 2    35
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>
# Average age: 30.0

# ✅ Expected output:
# 0    25
# 1    30
# 2    35
# Name: age, dtype: int64
# <class 'pandas.core.series.Series'>
# Average age: 30.0
import pandas as pd

df = pd.DataFrame({
    "product": ["Pen", "Notebook", "Eraser"],
    "price": [2, 5, 1],
    "stock": [100, 40, 250],
})

# 🎯 YOUR TURN: print how many rows and columns this DataFrame has
# Replace ___ with the correct attribute
print(df.___)

# Expected output:
# (3, 3)

📋 Quick Reference

Attribute / ActionReturns
df.shape(rows, columns) tuple
df.columnsColumn names
df.indexRow labels
df.dtypesType of each column
df["col"]A single column as a Series

🎯 Mini Challenge: Class Roster

Build a roster and explore its structure:

import pandas as pd

roster = pd.DataFrame({
    "name": ["Ana", "Ben", "Cara", "Dan"],
    "grade": [88, 72, 95, 60],
    "passed": [True, True, True, False],
})

print("Shape:", roster.shape)
print(roster.dtypes)
print("Average grade:", roster["grade"].mean())

# Output:
# Shape: (4, 3)
# name      object
# grade      int64
# passed      bool
# dtype: object
# Average grade: 78.75

# ✅ Expected output:
# Shape: (4, 3)
# name      object
# grade      int64
# passed      bool
# dtype: object
# Average grade: 78.75

❓ Frequently Asked Questions

Lesson complete — you understand the DataFrame!

You know a DataFrame is a 2-D table whose columns are Series, you can build one from a dict of lists, inspect its shape, columns, index, and dtypes, and pull out a single column as a Series.

Practice quiz

What is a pandas DataFrame?

  • A one-dimensional labelled array
  • A Python dictionary
  • A two-dimensional table with labelled rows and columns
  • A NumPy scalar

Answer: A two-dimensional table with labelled rows and columns. A DataFrame is a 2-D table of labelled rows and columns, like a spreadsheet.

What is each column of a DataFrame?

  • A Series
  • A list
  • A dict
  • A NumPy array with no index

Answer: A Series. Each column is a Series, and all columns share the same row index.

What does df['age'] return when 'age' is one column?

  • A DataFrame
  • A list
  • A scalar
  • A Series

Answer: A Series. Selecting a single column with square brackets returns a Series.

What does df.shape return?

  • A list of column names
  • A (rows, columns) tuple
  • The number of rows only
  • The dtypes

Answer: A (rows, columns) tuple. shape is a (rows, columns) tuple describing the table's size.

For a 3-row, 3-column DataFrame, what is df.shape?

  • (3, 3)
  • (9,)
  • (3,)
  • (1, 9)

Answer: (3, 3). Three rows and three columns gives the tuple (3, 3).

Which attribute lists the column names?

  • df.index
  • df.dtypes
  • df.columns
  • df.shape

Answer: df.columns. df.columns holds the column names; df.index holds the row labels.

Which attribute shows the data type of each column?

  • df.shape
  • df.dtypes
  • df.columns
  • df.values

Answer: df.dtypes. df.dtypes reports each column's dtype.

Why is df.shape written without parentheses?

  • It is a method that takes no args
  • Parentheses are optional
  • It returns a function
  • It is an attribute, not a method

Answer: It is an attribute, not a method. shape, columns, index, and dtypes are attributes — no parentheses.

Can different columns of one DataFrame hold different data types?

  • No, all must match like a NumPy array
  • Yes, each column can have its own dtype
  • Only numeric types are allowed
  • Only if they share an index

Answer: Yes, each column can have its own dtype. Unlike a NumPy array, each DataFrame column can hold a different dtype.

Because a selected column is a Series, which operation still works on df['age']?

  • Nothing — Series have no methods
  • Only printing
  • df['age'].mean()
  • Only len()

Answer: df['age'].mean(). It is a Series, so Series methods like .mean() and arithmetic still apply.

Continue this course

Frequently asked questions

What is a Pandas DataFrame?

A DataFrame is a two-dimensional, table-like data structure with labelled rows and columns — like a spreadsheet or SQL table. Each column is a Pandas Series, and all columns share the same row index.

Is each column of a DataFrame a Series?

Yes. Selecting a single column with df['col'] returns a Series — a one-dimensional labelled array. A DataFrame is essentially a collection of Series that all share one common index.

How do I check the size of a DataFrame?

Use df.shape, which returns a (rows, columns) tuple. df.columns lists the column names, df.index lists the row labels, and df.dtypes shows the data type of each column.

Can columns in a DataFrame have different data types?

Yes. Unlike a NumPy array, each DataFrame column can hold a different dtype — one column can be integers, another floats, another strings — which is what makes it ideal for real-world tabular data.