Pandas to Lists: Columns, Rows, Headers and Index Labels

Convert a column with tolist() or table rows with to_numpy().tolist(). Decide how headers, identifiers, dtypes and missing values should be represented.

Create the student table 🔝

A Series has tolist() and to_list(). A DataFrame has no direct tolist() method: use to_numpy().tolist() for nested rows or to_dict() for labelled records.

import pandas as pd
from io import BytesIO
df = pd.DataFrame({
    "NAME": ["Ravi", "Raju", "Alex", "Ron", "King", "Jack"],
    "ID": [1, 2, 3, 4, 5, 6],
    "MATH": [80, 40, 70, 70, 60, 30],
    "ENGLISH": [80, 70, 40, 50, 60, 30]
})
print(df)

Expected output

   NAME  ID  MATH  ENGLISH
0  Ravi   1    80       80
1  Raju   2    40       70
2  Alex   3    70       40
3   Ron   4    70       50
4  King   5    60       60
5  Jack   6    30       30

Convert the table to a nested list 🔝

Each inner list follows the current column order. Column names and index labels are not included. The values attribute also supports this conversion, but to_numpy() makes the conversion explicit.

rows = df.to_numpy().tolist()
legacy_rows = df.values.tolist()
print(type(rows).__name__)
print(rows)
assert rows == legacy_rows
assert rows[0] == ["Ravi", 1, 80, 80]

Expected output

list
[['Ravi', 1, 80, 80], ['Raju', 2, 40, 70], ['Alex', 3, 70, 40], ['Ron', 4, 70, 50], ['King', 5, 60, 60], ['Jack', 6, 30, 30]]

Add column names as a real list 🔝

Convert columns to a list before inserting them. Inserting df.columns directly inserts an Index object rather than a header list. list.insert() adds the header row.

table = df.to_numpy().tolist()
table.insert(0, df.columns.tolist())
print(table)
assert isinstance(table[0], list)
assert table[0] == ["NAME", "ID", "MATH", "ENGLISH"]

Expected output

[['NAME', 'ID', 'MATH', 'ENGLISH'], ['Ravi', 1, 80, 80], ['Raju', 2, 40, 70], ['Alex', 3, 70, 40], ['Ron', 4, 70, 50], ['King', 5, 60, 60], ['Jack', 6, 30, 30]]

Convert one column to a flat list 🔝

Series.tolist() returns values without labels. For a list of distinct values use unique() first when deduplication is part of your rule.

names = df["NAME"].tolist()
print(names)
print("Equivalent alias:", df["NAME"].to_list())
assert names == df["NAME"].to_list()

Expected output

['Ravi', 'Raju', 'Alex', 'Ron', 'King', 'Jack']
Equivalent alias: ['Ravi', 'Raju', 'Alex', 'Ron', 'King', 'Jack']

Convert index labels to a list 🔝

Index.tolist(), list(index) and the original values-based alternatives produce the same labels for this simple integer index. A MultiIndex produces tuples representing complete labels.

indexed = df.set_index("ID")
labels = indexed.index.tolist()
print(labels)
assert labels == indexed.index.values.tolist()
assert labels == list(indexed.index)
assert labels == list(indexed.index.values)
multi = df.set_index(["NAME", "ID"])
print("MultiIndex labels:", multi.index.tolist())

Expected output

[1, 2, 3, 4, 5, 6]
MultiIndex labels: [('Ravi', 1), ('Raju', 2), ('Alex', 3), ('Ron', 4), ('King', 5), ('Jack', 6)]

Preserve identifiers before converting rows 🔝

If an ID exists only in the index, reset it to a column before converting. Otherwise the row lists lose the identifier. See reset_index().

indexed = df.set_index("ID")
rows_with_id = indexed.reset_index().to_numpy().tolist()
print(rows_with_id)
assert rows_with_id[0][0] == 1

Expected output

[[1, 'Ravi', 80, 80], [2, 'Raju', 40, 70], [3, 'Alex', 70, 40], [4, 'Ron', 70, 50], [5, 'King', 60, 60], [6, 'Jack', 30, 30]]

Select and order the desired fields 🔝

Choose columns and row filters before conversion. This makes the positional meaning of each field explicit. See loc and row filtering.

selected = df.loc[df["MATH"].ge(70), ["ID", "NAME", "MATH"]]
result = selected.to_numpy().tolist()
print(result)
assert [row[0] for row in result] == [1, 3, 4]

Expected output

[[1, 'Ravi', 80], [3, 'Alex', 70], [4, 'Ron', 70]]

Watch for dtype conversion in a common array 🔝

A NumPy array has a common dtype. Numeric columns can be coerced, for example integers becoming floats when combined with a float column. For preserving per-column scalar types, construct rows through itertuples() or use labelled records.

mixed = pd.DataFrame({"id": [1, 2], "amount": [5.5, 8.0]})
array_rows = mixed.to_numpy().tolist()
tuple_rows = [list(row) for row in mixed.itertuples(index=False, name=None)]
print("Array rows:", array_rows)
print("Tuple rows:", tuple_rows)
assert isinstance(array_rows[0][0], float)
assert isinstance(tuple_rows[0][0], int)

Expected output

Array rows: [[1.0, 5.5], [2.0, 8.0]]
Tuple rows: [[1, 5.5], [2, 8.0]]

Choose how missing values leave Pandas 🔝

Lists can contain Pandas missing scalars or NaN. If a consumer expects None, replace missing values explicitly in an object-typed table. This does not make timestamps or every other type JSON-compatible.

nullable = pd.DataFrame({"id": [1, 2], "quantity": pd.Series([3, pd.NA], dtype="Int64")})
print("Series list:", nullable["quantity"].tolist())
objects = nullable.astype(object)
normalized = objects.where(nullable.notna(), None)
rows = normalized.to_numpy().tolist()
print("None policy:", rows)
assert rows[1][1] is None
assert nullable["quantity"].isna().sum() == 1

Expected output

Series list: [3, <NA>]
None policy: [[1, 3], [2, None]]

Read Excel data to create a choice list 🔝

This in-memory colour workbook illustrates the Name column from the Excel example. For your file, pass its path to read_excel(). Excel needs openpyxl; other cells can continue if it is unavailable.

colours = pd.DataFrame({"Name": ["Red", "Green", "Blue"], "Hex": ["#FF0000", "#008000", "#0000FF"]})
try:
    import openpyxl
except ImportError:
    print("Excel example requires openpyxl; embedded choices:", colours["Name"].tolist())
else:
    workbook = BytesIO()
    colours.to_excel(workbook, index=False, engine="openpyxl")
    workbook.seek(0)
    imported = pd.read_excel(workbook, engine="openpyxl")
    choices = imported["Name"].tolist()
    print(choices)
    assert choices == ["Red", "Green", "Blue"]

Expected output

['Red', 'Green', 'Blue']

Practical example: normalize dropdown choices 🔝

This synthetic product list contains repeated labels, whitespace and missing values. Define the case policy before merging labels; here case-insensitive comparison is intended. Keep a raw source for review.

raw_products = pd.Series([" Pen ", "pen", "Book", "", None, "Pencil"], dtype="string")
clean = raw_products.str.strip().str.casefold()
clean = clean.mask(clean.eq(""))
choices = sorted(clean.dropna().unique().tolist())
print("Choices:", choices)
print("Missing rows:", clean.isna().sum())
assert choices == ["book", "pen", "pencil"]

Expected output

Choices: ['book', 'pen', 'pencil']
Missing rows: 2

Prepare nested rows for a printable table 🔝

Keep a header list and one value list per row. Format values for the report separately from stored numeric data. Follow the DataFrame PDF-table tutorial to pass the prepared rows to a PDF library.

sales = pd.DataFrame({"order_id": [101, 102, 103], "product": ["Pen", "Book", "Pencil"], "amount": [5.25, 20.0, 8.5]})
display = sales.copy()
display["amount"] = display["amount"].map(lambda value: f"{value:.2f}")
pdf_rows = [display.columns.tolist()] + display.to_numpy().tolist()
print(pdf_rows)
assert len(pdf_rows) == len(sales) + 1
assert sales["amount"].sum() == 33.75

Expected output

[['order_id', 'product', 'amount'], [101, 'Pen', '5.25'], [102, 'Book', '20.00'], [103, 'Pencil', '8.50']]

Use labelled records when column positions are fragile 🔝

to_dict(orient="records") preserves column labels in each record. to_dict(orient="list") produces one list per column. Pick the representation expected by the receiving application.

records = sales.to_dict(orient="records")
by_column = sales.to_dict(orient="list")
print(records)
print(by_column)
assert records[0]["order_id"] == 101
assert by_column["product"] == ["Pen", "Book", "Pencil"]

Expected output

[{'order_id': 101, 'product': 'Pen', 'amount': 5.25}, {'order_id': 102, 'product': 'Book', 'amount': 20.0}, {'order_id': 103, 'product': 'Pencil', 'amount': 8.5}]
{'order_id': [101, 102, 103], 'product': ['Pen', 'Book', 'Pencil'], 'amount': [5.25, 20.0, 8.5]}

Restore a simple table from header and row lists 🔝

Supply columns explicitly when rebuilding a DataFrame. This recovers the values in this example, but does not automatically restore original extension dtypes, category definitions or an index.

table = [sales.columns.tolist()] + sales.to_numpy().tolist()
restored = pd.DataFrame(table[1:], columns=table[0])
print(restored)
assert restored.equals(sales)

Expected output

   order_id product  amount
0       101     Pen    5.25
1       102    Book   20.00
2       103  Pencil    8.50

Common questions 🔝

Why does df.tolist() fail? DataFrame has no direct tolist() method. Are headers included? No; add columns.tolist() when required. Is the index included? No; reset meaningful labels first. Does conversion change the table? It returns a new list; changing simple scalar items in it does not update the table. Nested mutable Python objects may still share references. Will large conversion use memory? It materializes the selected values as Python lists; select only the required data. Continue with describe(), head(), to_string() and rename().

Exercise: list students below 50 in Maths 🔝

Create a list of lists containing ID, NAME and MATH for students below 50 in Maths. Add a real header list and predict the number of rows including the header.

Exercise solution 🔝

Raju and Jack match. The result has one header and two data rows.

selected = df.loc[df["MATH"].lt(50), ["ID", "NAME", "MATH"]]
answer = [selected.columns.tolist()] + selected.to_numpy().tolist()
print(answer)
assert len(answer) == 3
assert [row[0] for row in answer[1:]] == [2, 6]

Expected output

[['ID', 'NAME', 'MATH'], [2, 'Raju', 40], [6, 'Jack', 30]]

Practice in Google Colab 🔝

Open in Google Colab View on GitHub
Run the examples in order, change selected fields and missing values, then inspect flat lists and nested rows. Save your own copy to keep edits. All sample tables are included in the notebook.

Reference: Pandas Series.to_list documentation.




Subscribe to our YouTube Channel here



plus2net.com







Python Video Tutorials
Python SQLite Video Tutorials
Python MySQL Video Tutorials
Python Tkinter Video Tutorials
✖
We use cookies to improve your browsing experience. . Learn more
HTML MySQL PHP JavaScript ASP Photoshop Articles Contact us
© 2000-2026 plus2net.com All rights reserved worldwide Privacy Policy Disclaimer