Skip to content
wannacode

The first chart

In short: A chart in matplotlib is a figure with axes: plot draws a line, bar draws bars, and the title, the axis labels and the legend say what is shown.

Problem

“Show me the year”

The manager wants to see how the year is going. You already know how to work out the revenue by month: the order lines without the cancelled ones, summed by month. The month is the first 7 characters of ordered_at, for example “2026-03”:

Pythondata: the shop tables

The numbers are right, but in 12 rows it is hard to see what is a peak and what is a drop. December is €15,915.90 and January is €7,228.20. How big is the drop compared with the other months? In a table the eye does not catch it. In a line it does at once.

The idea

Figure and axes

In the lesson “Welcome” you saw a chart made with one line of code. Now you will see what stands behind it.

A chart in matplotlib has two objects:

  • the figure (Figure) is the whole sheet: the size and saving to a file;
  • the axes (Axes) is the box with the horizontal and the vertical axis, where you draw.

plt.subplots() gives you both: fig, ax = plt.subplots(). Then you draw in the axes. ax.plot(x, y) joins the points with a line:

Pythondata: the shop tables

[chart] in the text of the output means that the chart has no title. The line already shows the peak in December and the dip after it. It still lacks three things: a title, labels on the axes, and months you can read.

More precisely, if you are curious

Here and in Jupyter the chart shows by itself at the end of the cell, which is why there is no plt.show(). In a script (python chart.py) you show it with plt.show() or save it with fig.savefig('monthly.png'). Otherwise the script ends and the figure goes with it.

plt.plot(...) without fig, ax draws too: matplotlib then takes the “current” axes by itself. That is handy for one quick chart, but with several axes you do not know which one is current. That is why here you always draw in named axes.

The idea

Title, labels and ticks

A chart without labels makes the reader guess. The axes have a method for each thing:

  • ax.set_title says what you are looking at;
  • ax.set_xlabel and ax.set_ylabel say what is along the bottom and what is up the side;
  • ax.tick_params(axis='x', labelrotation=45) rotates the tick labels, the numbers and names under the axis, so they do not overlap;
  • fig.tight_layout() arranges the sheet so the rotated labels are not cut off.

marker='o' puts a dot on every month:

Pythondata: the shop tables

Now you can see that 11 months are between €7,000 and €10,000, and December is above €15,000. January, February and September are the lowest. Why September drops, you will find out in the project.

Try it

Orders by month

Draw the number of orders in every month (without the cancelled ones) as a line. Store the counts in counts, and give the chart a title and labels on both axes.

Pythondata: the shop tables

The idea

Bars: ax.bar

A line joins points and says “from here to here something changed”. That makes sense for months that come one after another. Categories do not come one after another: for them you draw bars (a bar chart) with ax.bar(names, values).

The revenue by category needs the category name on every line: product → category_id → name. Two map calls give it:

Pythondata: the shop tables

There are 6 bars, and they add up to €107,466.20. The revenue of the year is €111,186.20. €3,720 is missing: the gift card has no category, map gives it NaN, and groupby skips NaN silently. The chart looks fine. So count the bars and compare their sum with the revenue.

Try it

All the categories

Draw the revenue by category so that the gift card is a bar of its own. Store the revenue by category in by_cat, and add a title and a label on the vertical axis.

Pythondata: the shop tables

The idea

The shortcut: df.plot

Series and DataFrame have a plot method. It calls matplotlib for you: kind='line' (the default), kind='bar' and the other kinds that come in the next lessons. With ax=ax it draws in your axes. Then you finish them with the methods of the axes, as before:

Pythondata: the shop tables

pandas has put the category names under the bars and rotated them. It has also put a label along the bottom: the name of the index, category. The title and the vertical label come from your code.

Both ways give the same chart. ax.bar gives you full control. df.plot saves lines when the data is already in a Series or a table.

1. You have made fig, ax = plt.subplots(). Where does monthly.plot(ax=ax) draw?

The idea

Several lines and a legend

December is the peak of the year. Do all the categories grow the same? Two lines in one axes answer that. Every ax.plot adds a line, label gives it a name, and ax.legend() adds the legend: a box that says which line is which:

Pythondata: the shop tables

Kitchen jumps from €964.80 in November to €3,240.60 in December, 3.4 times as much. Then it falls to €592.80 in January. The frying pan and the knives are probably bought as gifts. Dairy grows less: from €2,792.10 to €3,561.20.

A table with a column for every category df.plot draws in one go, a line per column, with a legend from the column names. That is why the table in the lesson on pivot_table is wide:

Pythondata: the shop tables

Seven lines in one axes already tangle. Which chart helps when, and how to show many series without tangling them, is the next lesson.

Exercise

Who carries December?

The two big groups of categories are Food and Home (parent_id in categories.csv). Draw the revenue of each by month as two lines in one axes, with a legend, a title and labels on the axes. Store the table by month and group in pv.

Pythondata: the shop tables

Test

Check yourself

1. Which of the two objects has set_title, set_xlabel and plot?
2. The month labels under the chart overlap. What helps?
3. You run the same code as a file chart.py in the terminal and see nothing. Why?
4. The gift card has no category. How many bars does lines.groupby("category")["revenue"].sum() give when drawn with ax.bar?
5. You have drawn two lines with ax.plot(...) and called ax.legend(), but the legend is empty. Why?

Made by Ivo Gergov as part of Evo Tech's campaign for accessible programming education ·