Python
Scikit-learn
Machine Learning
Data Analysis
Classification Report

Scikit classification report - change the format of displayed results

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

sklearn.metrics.classification_report is handy because it shows precision, recall, F1-score, and support in one place. The catch is that the default output is a preformatted text block aimed at quick inspection, not custom reporting. If you want a different display format, the clean approach is to ask for structured data and format it yourself.

What the Default Report Gives You

A basic call returns a formatted string:

python
1from sklearn.metrics import classification_report
2
3y_true = [0, 1, 0, 1, 1]
4y_pred = [0, 1, 0, 0, 1]
5
6print(classification_report(y_true, y_pred))

That is useful for terminal output, but it becomes limiting if you need:

  • different decimal precision
  • renamed class labels
  • a pandas table
  • JSON for an API or experiment log

The text report is convenient, but it is also the least flexible representation.

Use digits for Small Formatting Changes

If the only issue is numeric precision, use the digits parameter:

python
1from sklearn.metrics import classification_report
2
3y_true = [0, 1, 0, 1, 1]
4y_pred = [0, 1, 0, 0, 1]
5
6print(classification_report(y_true, y_pred, digits=4))

This changes how many decimal places are displayed. It does not change the metric calculation itself.

That makes digits the right answer when you want a slightly different report but still intend to print the built-in string.

Use output_dict=True for Full Control

For real customization, request the report as a dictionary:

python
1from sklearn.metrics import classification_report
2
3y_true = [0, 1, 0, 1, 1]
4y_pred = [0, 1, 0, 0, 1]
5
6report = classification_report(y_true, y_pred, output_dict=True)
7print(report)

Now you have raw numeric values organized by class and aggregate rows. From there you can reorder fields, rename rows, round selectively, or export the result in any structure you want.

This is the best route for dashboards, notebooks, services, and experiment-tracking systems.

Convert the Result to a DataFrame

A common next step is pandas:

python
1import pandas as pd
2from sklearn.metrics import classification_report
3
4y_true = [0, 1, 0, 1, 1]
5y_pred = [0, 1, 0, 0, 1]
6
7report = classification_report(y_true, y_pred, output_dict=True)
8df = pd.DataFrame(report).transpose()
9
10print(df.round(3))

This gives you a table that is much easier to manipulate. For example, you can pick only the columns you care about:

python
print(df[["precision", "recall", "f1-score", "support"]].round(2))

You can also export it with df.to_csv(...) or style it inside a notebook.

Rename Labels and Stabilize Edge Cases

If your class labels need human-readable names, pass target_names:

python
1from sklearn.metrics import classification_report
2
3y_true = [0, 1, 0, 1, 1]
4y_pred = [0, 1, 0, 0, 1]
5
6print(classification_report(
7    y_true,
8    y_pred,
9    target_names=["negative", "positive"]
10))

Another important option is zero_division. When a class has no predicted samples or no true samples, scikit-learn may emit warnings or fill metrics with zeros. If the report is part of an automated workflow, it is usually better to make that behavior explicit:

python
1from sklearn.metrics import classification_report
2
3y_true = [0, 0, 0, 1]
4y_pred = [0, 0, 0, 0]
5
6print(classification_report(y_true, y_pred, zero_division=0))

That keeps edge-case output stable.

JSON Output for Reporting Systems

Once you have a dictionary, JSON is straightforward:

python
1import json
2from sklearn.metrics import classification_report
3
4y_true = [0, 1, 0, 1, 1]
5y_pred = [0, 1, 0, 0, 1]
6
7report = classification_report(y_true, y_pred, output_dict=True)
8print(json.dumps(report, indent=2))

This is much better than parsing the pretty-printed text block when the result needs to be stored or transmitted.

Common Pitfalls

The biggest mistake is parsing the default text output with string operations. That is brittle and unnecessary because the function already offers structured output.

Another mistake is assuming digits changes the underlying metrics. It only changes how the text is displayed.

People also forget that rows such as accuracy, macro avg, and weighted avg are not shaped exactly like per-class rows, so DataFrame formatting should handle them intentionally.

Finally, if some classes are missing from predictions, do not ignore zero_division. Edge-case behavior matters when reports are generated automatically.

Summary

  • Use digits for simple display-only precision changes.
  • Use output_dict=True when you need real formatting control.
  • Convert the result to pandas for tabular reporting and export.
  • Use target_names and zero_division to improve readability and stability.
  • Avoid brittle string parsing when structured metrics are already available.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design