Plotting Data using Matplotlib
Overview
This chapter teaches students to turn data into pictures with Matplotlib's pyplot module and with the pandas plot() method. Students draw line plots, bar graphs and histograms, customise them with titles, labels, legends, colours, markers and line styles, and save them as image files for reports and projects.
The 2025-26 syllabus covers the purpose of plotting; drawing and saving line plots, bar graphs and histograms; and customising plots with labels, title and legend. Pie, scatter, box and area plots from the NCERT chapter are enrichment only. Practicals need at least 4 Matplotlib programs in the practical file.
Learning outcomes
- Students will be able to explain the purpose of data visualisation and choose a suitable chart (line, bar or histogram) for given data.
- Students will be able to draw line plots with plt.plot() and customise colour, marker, line style and line width.
- Students will be able to draw vertical, horizontal and grouped bar graphs with bar() and barh().
- Students will be able to draw histograms with hist(), choosing bins, edgecolor, histtype and cumulative, and read frequencies from them.
- Students will be able to add a title, axis labels, legend, grid and custom ticks, and set the figure size.
- Students will be able to save a chart in different formats with savefig().
- Students will be able to plot Series and DataFrames, including data read from CSV files, using df.plot(kind=...).
- Students will be able to complete, correct and predict the output of plotting code in board-style questions.
Lesson plan
Show the class a table of 30 students' marks and ask who can spot the trend in 10 seconds; then show the same data as a chart. Students list visualisations they see daily (speedometer, weather map, cricket worm). Introduce the three syllabus charts with the 'use it when' table on the board.
Lab: install/check Matplotlib, import pyplot as plt, and plot a week's temperature. Add title, xlabel, ylabel. Pair task: plot two students' unit-test marks with label= and legend(), then add grid().
Board: build the colour, marker and line-style code table with students. Lab challenge cards: 'draw a green dotted line with star markers, 3 points thick' in both long form and format-string form. Introduce figsize, xticks with rotation, yticks.
Lab: subject-wise average with bar(), colour list, width and edgecolor; then barh() for long names. Demonstrate the grouped bar trick (x - w/2, x + w/2) and the bug when both calls use the same x. Students compare boys and girls per section.
Hand count first: students tally a list of 20 marks into 10-mark intervals on paper, then check with hist() and the printed counts. Discuss the left-edge rule. Explore histtype='step' and cumulative=True. Board: bar graph vs histogram table.
Lab: savefig() in PNG, PDF and JPG; open the files to check. Deliberately put savefig() after show() to see the blank file, and discuss why.
Lab: df.plot(kind='line'/'bar'/'barh'/'hist') on a canteen or result DataFrame; read result.csv, set_index('Name') and plot selected columns. Students note what pandas does automatically (legend, x labels).
Quick demo of pie, scatter, box and area plots. Students pick an open dataset (for example from data.gov.in) for their project and decide which chart suits each question they want to answer.
Worksheet of fill-in-the-blank, error-finding and output-prediction questions; practical-file programs; a 20-minute quiz using the MCQs and assertion-reason items from this page.
Notes
Purpose of plotting data
Data visualisation means showing data as a picture: a chart, graph or diagram. A table of 500 numbers is hard to read, but a single chart can show the pattern in a few seconds.
We plot data to:
- see a trend over time (for example, the monthly fee collection of a school rising or falling);
- compare quantities (sales of five products, marks in five subjects);
- see the distribution of values (how many students scored 40-50, 50-60 and so on);
- spot outliers and mistakes in data (a mark of 950 entered instead of 95);
- communicate results to people who will not read the raw numbers (parents, principals, managers).
Everyday examples of visualisation are the speedometer of a scooter, a weather map on the news, a cricket run-rate graph (the worm) and an ECG report.
| Chart | Use it when you want to show | School example |
|---|---|---|
| Line plot | Change over time or an ordered sequence | Marks of a student across four unit tests |
| Bar graph | Comparison between separate categories | Average marks in each subject |
| Histogram | How numeric data is spread over intervals (frequency) | Number of students in the 40-50, 50-60, ... marks ranges |
The 2025-26 CBSE syllabus names exactly three plot types: line plot, bar graph and histogram, plus adding a label, title and legend, and saving a plot. Pie, scatter, box and area plots are enrichment only.
Matplotlib and the pyplot module
Matplotlib is a Python library for drawing 2D charts. It is not part of standard Python, so it is installed once with pip install matplotlib at the command prompt.
Its pyplot module contains simple functions such as plot(), bar(), hist(), title() and show(). By convention it is imported with the alias plt.
Every chart is drawn on a figure (the whole window or image). Inside the figure is a plot area (axes) with an x-axis and a y-axis. Each pyplot call adds something to the current figure, and plt.show() finally displays it.
Steps to draw any chart:
- Import pyplot:
import matplotlib.pyplot as plt - Prepare the data in lists, NumPy arrays or a pandas Series/DataFrame.
- Call a plotting function such as
plt.plot(x, y). - Customise: title, axis labels, legend, grid, colours.
- Save with
plt.savefig()(optional) and display withplt.show().
import matplotlib.pyplot as plt
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
temp = [31, 33, 34, 32, 35, 36, 34] # maximum temperature in Jaipur (deg C)
plt.plot(days, temp)
plt.show()The output is a single blue line joining seven points, with the day names on the x-axis and temperatures on the y-axis. There is no title or label yet: point out to students that an unlabelled chart is incomplete, and board answers lose marks for it.
Line plot with title, axis labels, legend and grid
plt.plot(x, y) joins the points (x, y) with straight lines. If only one list is given, as in plt.plot(y), Python uses 0, 1, 2, ... as the x values.
To make a chart readable we add:
plt.title('text'): heading at the top of the chart;plt.xlabel('text')andplt.ylabel('text'): names of the x-axis and y-axis;plt.legend(): a small box that tells which line is which. It uses thelabel=given to eachplot()call;plt.grid(True): background grid lines that help read values.
Calling plot() more than once before show() draws several lines on the same chart, each in a new default colour.
import matplotlib.pyplot as plt
tests = ['UT1', 'UT2', 'UT3', 'UT4']
riya = [68, 74, 81, 88]
kabir = [72, 70, 77, 79]
plt.plot(tests, riya, label='Riya')
plt.plot(tests, kabir, label='Kabir')
plt.title('Unit Test Marks in Informatics Practices')
plt.xlabel('Unit Test')
plt.ylabel('Marks (out of 100)')
plt.legend()
plt.grid(True)
plt.show()plt.legend() shows labels only for lines drawn with label=. Another way is plt.legend(['Riya', 'Kabir']), where the names are given in the order the lines were drawn. The loc parameter moves the box, for example plt.legend(loc='upper left').
Customising lines: color, marker, linestyle, linewidth
Optional keyword arguments of plot() change how a line looks:
color(orc): a name such as'red', a one-letter code such as'r', or a hex code such as'#1f77b4';marker: a symbol drawn at each data point, such as'o','*','s','^','D','+','x';markersize(orms) andmarkeredgecolor: size and border colour of the marker;linestyle(orls):'-'or'solid','--'or'dashed',':'or'dotted','-.'or'dashdot';linewidth(orlw): thickness of the line in points (default 1.5).
A short format string combines colour, marker and line style in one argument. 'ro--' means red, circle markers, dashed line. 'g^:' means green, triangle markers, dotted line.
| Code | Colour | Code | Marker | Code | Line style |
|---|---|---|---|---|---|
| 'b' | blue | 'o' | circle | '-' | solid |
| 'g' | green | 's' | square | '--' | dashed |
| 'r' | red | '^' | triangle up | ':' | dotted |
| 'c' | cyan | '*' | star | '-.' | dash-dot |
| 'm' | magenta | 'D' | diamond | ||
| 'y' | yellow | '+' / 'x' | plus / cross | ||
| 'k' | black | '.' | point | ||
| 'w' | white | 'p' / 'h' | pentagon / hexagon |
import matplotlib.pyplot as plt
overs = [1, 2, 3, 4, 5, 6]
india = [8, 14, 25, 31, 42, 55]
australia = [6, 15, 21, 30, 37, 44]
plt.plot(overs, india, color='blue', marker='o', markersize=8,
linestyle='--', linewidth=2, label='India')
plt.plot(overs, australia, 'y^:', linewidth=3, label='Australia')
plt.title('Powerplay: cumulative runs')
plt.xlabel('Over')
plt.ylabel('Runs')
plt.legend()
plt.show()Black is 'k', not 'b' (that is blue). This is a favourite one-mark question. Also note the spelling: the parameter is color (American spelling). Writing colour= gives an error.
Figure size, xticks and yticks
plt.figure(figsize=(width, height))sets the size of the figure in inches. It must be called before the plotting function. The default is about 6.4 x 4.8 inches.plt.xticks(positions, labels)decides where the marks (ticks) on the x-axis appear and what text is written there.rotation=45tilts long labels so they do not overlap.plt.yticks()does the same for the y-axis.plt.xlim()andplt.ylim()set the range of an axis.
In the example, the months are stored as numbers 1 to 12, and xticks() replaces the numbers with month names.
import matplotlib.pyplot as plt
month = list(range(1, 13))
rain = [1, 0, 1, 1, 11, 520, 840, 590, 340, 90, 15, 4] # Mumbai, mm (approx.)
names = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
plt.figure(figsize=(10, 4))
plt.plot(month, rain, color='navy', marker='s')
plt.xticks(month, names, rotation=45)
plt.yticks(range(0, 901, 100))
plt.title('Average monthly rainfall in Mumbai')
plt.xlabel('Month')
plt.ylabel('Rainfall (mm)')
plt.grid(True)
plt.show()The chart is wide and short, the x-axis shows tilted month names instead of 1-12, and the y-axis has a tick every 100 mm. The sharp peak in July makes the monsoon pattern obvious, which is a good discussion point on why a line plot suits time-ordered data.
Bar graph: plt.bar()
A bar graph compares values of separate categories. Each category gets one rectangular bar whose height is the value. Bars have gaps between them because the categories are not continuous.
Syntax: plt.bar(x, height, width=0.8, color=..., edgecolor=..., label=...)
x: category names or positions;height: the values;width: width of each bar (default 0.8);color: one colour for all bars, or a list with one colour per bar;edgecolorandlinewidth: border colour and thickness of the bars.
import matplotlib.pyplot as plt
subjects = ['English', 'Maths', 'Physics', 'Chemistry', 'IP']
average = [72, 65, 61, 68, 81]
plt.bar(subjects, average, width=0.6,
color=['tomato', 'orange', 'gold', 'yellowgreen', 'skyblue'],
edgecolor='black')
plt.title('Class XII-B: subject-wise average marks')
plt.xlabel('Subject')
plt.ylabel('Average marks')
plt.show()Ask students: "Would a line plot be right here?" No. Joining English to Maths with a line suggests a trend between subjects, which is meaningless. Use a line plot for ordered data (time), a bar graph for categories.
Horizontal bar graph: plt.barh()
plt.barh(y, width) draws bars that run left to right. It is useful when category names are long or there are many categories.
In barh(), the categories go on the y-axis and the values on the x-axis, so the axis labels swap: the values are named with xlabel(). The thickness of each bar is set with height= (default 0.8), because width now means the length of the bar.
import matplotlib.pyplot as plt
players = ['Shubman', 'Yashasvi', 'Rinku', 'Tilak', 'Hardik']
runs = [412, 375, 298, 260, 214]
plt.barh(players, runs, color='darkorange', height=0.5)
plt.title('Runs scored in the series')
plt.xlabel('Runs')
plt.ylabel('Batter')
plt.show()Comparing two sets of data: grouped (multiple) bar graph
To compare two values for every category (boys and girls in each section, 2024 and 2025 sales of each product) we draw two bar() calls side by side.
The trick is to shift the x positions. We use numbers 0, 1, 2, ... as positions (with numpy.arange()), draw the first set at x - w/2 and the second at x + w/2, where w is the bar width. Finally xticks() puts the category names back under each pair, and legend() tells which colour is which.
import matplotlib.pyplot as plt
import numpy as np
sections = ['XII-A', 'XII-B', 'XII-C', 'XII-D']
boys = [18, 20, 15, 17]
girls = [16, 14, 19, 18]
x = np.arange(len(sections)) # positions 0, 1, 2, 3
w = 0.35
plt.bar(x - w/2, boys, width=w, color='steelblue', label='Boys')
plt.bar(x + w/2, girls, width=w, color='hotpink', label='Girls')
plt.xticks(x, sections)
plt.title('Strength of Class XII sections')
plt.xlabel('Section')
plt.ylabel('Number of students')
plt.legend()
plt.show()Without NumPy, students can build the shifted positions with a list comprehension: x = [0, 1, 2, 3] and x2 = [i + 0.35 for i in x]. If both bar() calls use the same x values, the second set of bars hides the first. This is a common practical-exam mistake.
Histogram: plt.hist() and bins
A histogram shows the frequency distribution of numeric data. The range of the data is divided into intervals called bins, and the height of each bar is the number of values that fall in that bin. Because the bins are continuous, the bars touch each other (no gaps).
Syntax: plt.hist(x, bins=10, color=..., edgecolor=..., histtype='bar', cumulative=False)
x: a single list, array or Series of numbers (the raw data, not counts);binsas an integer: that many equal-width bins from the minimum to the maximum value (default 10);binsas a list of edges, for example[40, 50, 60, 70]: bins 40-50, 50-60 and 60-70;edgecolor: colour of the bar borders, which makes adjacent bars easy to see.
Boundary rule: every bin includes its left edge and excludes its right edge, except the last bin, which includes both. So with edges [40, 50, 60], a mark of 50 is counted in the 50-60 bin, and a mark of 60 is counted in the last bin.
plt.hist() also returns the counts, the bin edges and the drawn bars, so we can print the frequency table.
import matplotlib.pyplot as plt
marks = [45, 52, 58, 61, 63, 67, 68, 70, 72, 74,
75, 77, 78, 81, 83, 85, 88, 90, 92, 97]
counts, edges, bars = plt.hist(marks, bins=[40, 50, 60, 70, 80, 90, 100],
color='skyblue', edgecolor='black')
print('Frequencies:', counts)
print('Bin edges :', edges)
plt.title('Distribution of IP marks, Class XII-A')
plt.xlabel('Marks')
plt.ylabel('Number of students')
plt.show()Frequencies: [1. 2. 4. 6. 4. 3.] Bin edges : [ 40. 50. 60. 70. 80. 90. 100.]
Make students count by hand first: 70 goes in 70-80 (left edge included), 90 goes in 90-100. Then run the code and match their counts with the printed frequencies. This removes the most common confusion about bins.
Histogram options: histtype and cumulative
histtypecontrols the drawing style:'bar'(default): ordinary filled bars;'barstacked': when several data sets are given, their bars are stacked on top of each other;'step': only the outline is drawn, with no fill. Useful to compare two data sets on one chart;'stepfilled': an outline that is filled in, with no lines between bars.cumulative=True: each bar shows the count of all values up to and including that bin. The last bar always equals the total number of values. This answers questions such as "How many students scored below 70?"- Other useful parameters:
alpha(transparency between 0 and 1),orientation='horizontal', andrange=(low, high).
| Bar graph | Histogram |
|---|---|
| Compares separate categories | Shows the distribution of continuous numeric data |
| Gaps between bars | No gaps: bars touch |
| Each bar is one category; you supply the heights | Each bar is an interval (bin); Python counts the values in it |
| Order of bars can be changed | Order of bins is fixed (numeric scale) |
| Function: bar() / barh() | Function: hist() |
import matplotlib.pyplot as plt
heights = [142, 145, 147, 149, 150, 151, 152, 153, 154, 155,
156, 156, 157, 158, 159, 160, 161, 163, 165, 168]
counts, edges, bars = plt.hist(heights, bins=[140, 145, 150, 155, 160, 165, 170],
cumulative=True, histtype='step',
color='purple', linewidth=2)
print('Cumulative counts:', counts)
plt.title('Heights of Class IX students (cumulative)')
plt.xlabel('Height (cm)')
plt.ylabel('Students up to this height')
plt.show()Cumulative counts: [ 1. 4. 9. 15. 18. 20.]
Saving a plot: plt.savefig()
plt.savefig('file name') writes the current figure to a file. The format is taken from the extension: .png, .jpg, .pdf, .svg and others. Useful parameters are dpi= (dots per inch, image quality) and bbox_inches='tight' (trims extra white space).
Call savefig() before show(). When the window opened by show() is closed, the figure is cleared, so a savefig() written after it saves a blank image.
A file name without a folder is saved in the current working folder. A full path can be given; on Windows use forward slashes or a raw string, for example plt.savefig('D:/IP/charts/sales.png') or plt.savefig(r'D:\IP\charts\sales.png').
import matplotlib.pyplot as plt
items = ['Samosa', 'Sandwich', 'Juice', 'Idli', 'Noodles']
sold = [120, 85, 60, 95, 70]
plt.bar(items, sold, color='seagreen')
plt.title('Canteen sales on Monday')
plt.xlabel('Item')
plt.ylabel('Plates sold')
plt.savefig('canteen_sales.png')
plt.savefig('canteen_sales.pdf', bbox_inches='tight')
plt.show()Board question pattern: "Write the statement to save the chart as sales.jpg". Answer: plt.savefig('sales.jpg'). Students often write plt.save() or plt.savefig(sales.jpg) without quotes. Both are wrong.
Plotting with pandas: df.plot(kind=...)
pandas Series and DataFrames have a plot() method that uses Matplotlib internally. One call draws the chart, adds a legend from the column names and labels the x-axis from the index.
General syntax: df.plot(kind='...', x='column', y='column or list', title='...', color=..., ...)
Values of kind used in the syllabus:
'line'(default): line plot, one line per numeric column;'bar': vertical bars; for several numeric columns the bars are grouped automatically;'barh': horizontal bars;'hist': histogram of the numeric columns (acceptsbins,edgecolor,cumulative).
Enrichment values: 'pie', 'scatter', 'box', 'area'.
Most Matplotlib parameters (color, marker, linestyle, linewidth, figsize, edgecolor) can be passed straight to df.plot(). Axis labels, savefig() and show() still come from plt, so we import both libraries.
import pandas as pd
import matplotlib.pyplot as plt
canteen = pd.DataFrame({
'Month': ['Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'],
'Tea': [520, 480, 300, 450, 470, 510],
'Coffee': [310, 290, 180, 260, 300, 330]
})
canteen.plot(kind='line', x='Month', y=['Tea', 'Coffee'],
marker='o', title='Cups sold in the staff canteen')
plt.ylabel('Cups')
plt.show()
canteen.plot(kind='bar', x='Month', color=['brown', 'peru'],
title='Tea vs Coffee (bar)')
plt.ylabel('Cups')
plt.show()The first chart has two lines with markers and a legend (Tea, Coffee) created automatically. The second has a pair of bars for each month. Remind students that with kind='bar' the x-axis labels are the index unless x= names a column.
pandas: kind='barh' and kind='hist'
df.plot(kind='barh', x='Name', y='Total')gives a horizontal bar chart; the categories are on the y-axis.df.plot(kind='hist', y='column', bins=..., edgecolor=...)gives a histogram of a column. Ifyis not given, all numeric columns are drawn as overlapping histograms, so name the column you want.Series.plot(kind='hist')works the same way on a single column, e.g.df['IP'].plot(kind='hist').
Both examples below use the same small result DataFrame.
import pandas as pd
import matplotlib.pyplot as plt
result = pd.DataFrame({
'Name': ['Aman', 'Bhavya', 'Chirag', 'Divya', 'Esha', 'Farhan', 'Gauri', 'Harsh'],
'Total': [412, 455, 380, 470, 398, 431, 446, 365]
})
result.plot(kind='barh', x='Name', y='Total', color='slateblue',
legend=False, title='Total marks (out of 500)')
plt.xlabel('Total marks')
plt.show()
result.plot(kind='hist', y='Total', bins=[350, 380, 410, 440, 470, 500],
edgecolor='black', title='Distribution of totals')
plt.xlabel('Total marks')
plt.show()Plotting data from a CSV file
In projects and practicals, data usually comes from a CSV file. The steps are:
- Read the file with
pd.read_csv(). - If needed, set a column as the index with
set_index()so it becomes the x-axis. - Select the columns to plot and call
plot().
The file result.csv used here has the columns shown in the table. In the code, set_index('Name') puts student names on the x-axis, and selecting three columns draws a grouped bar chart.
| Name | English | Maths | Physics | Chemistry | IP |
|---|---|---|---|---|---|
| Aarav | 78 | 85 | 72 | 69 | 91 |
| Diya | 88 | 92 | 81 | 84 | 95 |
| Ishaan | 65 | 58 | 61 | 70 | 74 |
| Meera | 91 | 76 | 79 | 88 | 89 |
| Rohan | 70 | 81 | 68 | 64 | 80 |
| Sana | 84 | 67 | 73 | 77 | 86 |
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('result.csv')
df = df.set_index('Name')
print(df.mean())
df[['English', 'Maths', 'IP']].plot(kind='bar', figsize=(9, 4),
edgecolor='black')
plt.title('Marks in three subjects')
plt.ylabel('Marks')
plt.xticks(rotation=0)
plt.savefig('three_subjects.png')
plt.show()English 79.333333 Maths 76.500000 Physics 72.333333 Chemistry 75.333333 IP 85.833333 dtype: float64
df.mean() here works because the only text column, Name, has been moved to the index. If Name were still a column, newer pandas versions raise an error; use df.mean(numeric_only=True) in that case.
Pie chart and scatter plot (Enrichment)
These are not in the CBSE 2025-26 syllabus but appear in the NCERT book and are useful for projects.
- Pie chart: shows parts of a whole as slices of a circle.
plt.pie(values, labels=..., autopct='%1.1f%%')prints the percentage on each slice. With pandas:df.plot(kind='pie', y='column'). - Scatter plot: shows the relationship between two numeric variables as unconnected dots.
plt.scatter(x, y); with pandas:df.plot(kind='scatter', x='col1', y='col2').
import matplotlib.pyplot as plt
transport = ['Bus', 'Walk', 'Cycle', 'Parent', 'Auto']
students = [420, 150, 110, 230, 90]
plt.pie(students, labels=transport, autopct='%1.1f%%')
plt.title('How students come to school')
plt.show()
hours = [1, 2, 2, 3, 4, 4, 5, 6, 6, 7]
score = [42, 50, 55, 58, 66, 70, 74, 80, 83, 90]
plt.scatter(hours, score, color='crimson', marker='D')
plt.title('Self-study hours vs test score')
plt.xlabel('Hours of self-study per day')
plt.ylabel('Score')
plt.show()Box plot and area plot (Enrichment)
- Box plot (box-and-whisker): summarises a column using the minimum, first quartile, median, third quartile and maximum, and marks outliers as separate dots. Good for comparing the spread of marks in two sections.
plt.boxplot(data)ordf.plot(kind='box'). - Area plot: a line plot with the area below the line filled in. With several columns the areas are stacked.
df.plot(kind='area').
import pandas as pd
import matplotlib.pyplot as plt
marks = pd.DataFrame({
'XII-A': [55, 62, 68, 70, 71, 74, 78, 81, 85, 97],
'XII-B': [40, 58, 60, 63, 66, 67, 69, 72, 75, 79]
})
marks.plot(kind='box', title='Spread of IP marks')
plt.ylabel('Marks')
plt.show()
energy = pd.DataFrame({'Solar': [20, 35, 50, 70],
'Grid': [80, 70, 60, 45]},
index=['2022', '2023', '2024', '2025'])
energy.plot(kind='area', title='School electricity sources (units x 100)')
plt.show()Quick reference: pyplot functions in this chapter
Teachers can project or print this table as a one-page revision sheet before the unit test.
| Function / parameter | Purpose | Example |
|---|---|---|
| plot() | Line plot | plt.plot(x, y, 'ro--') |
| bar() | Vertical bar graph | plt.bar(names, values, width=0.5) |
| barh() | Horizontal bar graph | plt.barh(names, values) |
| hist() | Histogram | plt.hist(data, bins=5, edgecolor='k') |
| title() | Chart heading | plt.title('Sales 2025') |
| xlabel() / ylabel() | Axis names | plt.xlabel('Month') |
| legend() | Key for several data sets | plt.legend(loc='upper right') |
| grid() | Background grid | plt.grid(True) |
| xticks() / yticks() | Tick positions and labels | plt.xticks([0, 1], ['A', 'B']) |
| figure(figsize=) | Size of chart in inches | plt.figure(figsize=(8, 4)) |
| savefig() | Save chart to a file | plt.savefig('chart.png') |
| show() | Display the chart | plt.show() |
| df.plot(kind=) | Plot from pandas | df.plot(kind='bar', x='Name') |
Key terms
- Data visualisation
- Representing data as charts or graphs so that patterns, trends and comparisons are easy to see.
- Matplotlib
- A Python library for creating 2D static, animated and interactive plots.
- pyplot
- The module of Matplotlib with simple functions such as plot(), bar(), hist() and show(); imported as plt.
- Figure
- The whole window or image on which one or more plots are drawn.
- Line plot
- A chart that joins data points with straight lines; used for trends over time.
- Bar graph
- A chart of rectangular bars, with gaps, whose lengths compare values of separate categories.
- Histogram
- A chart of touching bars showing how many values of numeric data fall in each interval.
- Bin
- One interval of a histogram; bins are set by the bins parameter of hist().
- Frequency
- The number of data values that fall in a bin.
- Legend
- A key on the chart that tells which colour or line stands for which data set.
- Marker
- A symbol (circle, star, square, ...) drawn at each data point of a line plot.
- Line style
- The pattern of a line: solid, dashed, dotted or dash-dot.
- Tick
- A small mark with a label along an axis; changed with xticks() and yticks().
- figsize
- A parameter giving (width, height) of a figure in inches.
- savefig()
- A pyplot function that saves the current figure to a file such as PNG, JPG, PDF or SVG.
- kind
- The parameter of pandas plot() that chooses the chart type: 'line', 'bar', 'barh', 'hist' and others.
- Cumulative histogram
- A histogram in which each bar counts all values up to and including that bin.
MCQs
Tap an option to check it, or use Show answers above to reveal them all.
-
Which Matplotlib module provides simple functions such as
plot(),bar()andhist()?Answer(b) matplotlib.pyplot
pyplot is the Matplotlib module with simple plotting functions. It is usually imported as
import matplotlib.pyplot as plt. -
What does
plt.xticks([0, 1, 2], ['Mon', 'Tue', 'Wed'])do?Answer(c) Shows the labels Mon, Tue and Wed at x positions 0, 1 and 2
The first list gives tick positions and the second gives the text shown at those positions.
-
By default,
plt.plot(x, y)draws:Answer(a) a line joining the points
plot() draws a line plot. Markers appear only if a marker is given.
-
Which function writes a name below the horizontal axis?
Answer(d) xlabel()
xlabel() names the x-axis; ylabel() names the y-axis; title() writes the heading.
-
A program calls
plt.plot(x, a)andplt.plot(x, b), thenplt.legend(), but no legend appears on the chart. What is the most likely reason?Answer(a) The
labelparameter was not given in the plot() callslegend() takes its text from the label= of each plotted line. Without labels there is nothing to show.
-
The format string
'g*--'inplt.plot(x, y, 'g*--')gives:Answer(c) a green dashed line with star markers
g = green, * = star marker, -- = dashed line.
-
Which value of
linestyledraws a dotted line?Answer(d) ':'
':' (or 'dotted') is dotted; '-' solid, '--' dashed, '-.' dash-dot.
-
Which colour code stands for black in Matplotlib?
Answer(b) 'k'
'k' is black. 'b' is blue.
-
Which parameter of
plot()makes the line thicker?Answer(a) linewidth
linewidth (or lw) sets the thickness of the line in points.
-
Which function draws bars from left to right, with categories on the y-axis?
Answer(d) barh()
barh() draws a horizontal bar graph.
-
What is the default width of each bar in
plt.bar()?Answer(b) 0.8
The default width is 0.8, which leaves a gap of 0.2 between bars placed at positions 0, 1, 2, ...
-
A histogram is the most suitable chart to show:
Answer(a) how the heights of 200 students are spread over intervals
A histogram shows the distribution of continuous numeric data over intervals. State populations need a bar graph and a daily price needs a line plot.
-
plt.hist(data, bins=5)divides the data into:Answer(c) 5 equal-width bins from the smallest to the largest value
An integer bins value gives that many equal-width intervals covering the range of the data.
-
With
bins=[0, 10, 20, 30], in which bin is the value 20 counted?Answer(c) 20-30
Each bin includes its left edge and excludes its right edge (except the last bin), so 20 goes in 20-30.
-
Which
histtypedraws only the outline of the histogram, without filling?Answer(b) 'step'
'step' draws an unfilled outline. 'stepfilled' fills it.
-
If
cumulative=Trueis passed tohist(), then:Answer(d) each bar shows the count of all values up to and including that bin
A cumulative histogram adds up counts, so the last bar equals the total number of values.
-
A student writes
plt.show()and thenplt.savefig('a.png'). The saved file is blank. Why?Answer(b) The figure is cleared once the shown window is closed, so savefig must come first
Always call savefig() before show().
-
Which file type can NOT be produced by
plt.savefig()?Answer(d) .docx
savefig supports image and vector formats such as png, jpg, pdf and svg, but not Word documents.
-
In
plt.figure(figsize=(8, 4)), the numbers 8 and 4 are:Answer(c) width and height in inches
figsize is (width, height) in inches.
-
A DataFrame
dfhas a column Month and two numeric columns, Tea and Coffee. What doesdf.plot(kind='bar', x='Month')draw?Answer(a) A grouped bar chart with one pair of bars per month and a legend for Tea and Coffee
pandas draws one bar per numeric column for each x value and builds the legend from the column names.
Assertion–Reason
Assertion (A): In a histogram there are no gaps between adjacent bars.
Reason (R): The bins of a histogram are continuous intervals; the right edge of one bin is the left edge of the next.
Answer(A)
Both are true and the continuity of bins is exactly why the bars touch.
Assertion (A):
plt.legend()can show a separate name for each line in a multi-line plot.Reason (R): The legend reads the text from the
labelparameter of eachplot()call.Answer(A)
Both are true and R explains how legend() knows the names.
Assertion (A): Calling
plt.savefig('x.png')afterplt.show()always saves the complete chart.Reason (R):
savefig()can save a chart in formats such as PNG, PDF and SVG.Answer(D)
A is false: after the shown window is closed the figure is cleared and a blank image is saved. R is true.
Assertion (A): A bar graph is suitable for comparing the sales of different products in a shop.
Reason (R): The bars of a bar graph must always be vertical.
Answer(C)
A is true. R is false: barh() draws horizontal bars.
Assertion (A): The
markerparameter shows a symbol at each data point of a line plot.Reason (R): The
linestyleparameter decides whether a line is solid, dashed or dotted.Answer(B)
Both statements are true, but the line style has nothing to do with markers, so R does not explain A.
Short answer
- 2 marks
What is data visualisation? Give two reasons why we plot data.
AnswerData visualisation is the graphical representation of data using charts and graphs.
Reasons: (1) trends and patterns, such as rising or falling sales, are seen at a glance; (2) it is easier to compare values and spot errors or outliers, and to communicate results to people who will not read raw numbers.
- 2 marks
Give two differences between a bar graph and a histogram.
Answer- A bar graph compares separate categories; a histogram shows the distribution of continuous numeric data over intervals.
- Bars of a bar graph have gaps; bars of a histogram touch each other. (Also: bar() is given the heights, hist() counts the values itself.)
- 2 marks
Fill in the blanks so that the program draws a line plot of runs scored in each over, with a title and an x-axis label.
import matplotlib.________ as pltovers = [1, 2, 3, 4, 5]runs = [6, 11, 4, 9, 14]plt.________(overs, runs)plt.________('Runs per over')plt.________('Over number')plt.show()
AnswerBlanks:
pyplot,plot,title,xlabel. Complete program:Python import matplotlib.pyplot as plt overs = [1, 2, 3, 4, 5] runs = [6, 11, 4, 9, 14] plt.plot(overs, runs) plt.title('Runs per over') plt.xlabel('Over number') plt.show() - 2 marks
Write a single statement to plot lists
xandyas a red dashed line, 3 points thick, with circle markers, and labelled 'Sales'.AnswerEither form is correct:
Python import matplotlib.pyplot as plt x = [1, 2, 3] y = [5, 7, 4] plt.plot(x, y, color='red', linestyle='--', linewidth=3, marker='o', label='Sales') # or: plt.plot(x, y, 'ro--', linewidth=3, label='Sales') plt.show() - 2 marks
What is the purpose of
plt.legend()? What must the programmer do for it to show meaningful text?Answerlegend() displays a key on the chart telling which colour, line or bar belongs to which data set. For it to show names, each plotting call must have a
label=argument (for exampleplt.plot(x, y, label='2025')), or the names must be passed as a list:plt.legend(['2024', '2025']). - 2 marks
Fill in the blanks to draw a histogram of the list
ageswith bins 10-20, 20-30, 30-40, 40-50 and 50-60, with black borders around the bars.plt.hist(ages, ________ = [________], ________ = 'black')Answerbins,10, 20, 30, 40, 50, 60andedgecolor:Python import matplotlib.pyplot as plt ages = [12, 18, 25, 27, 33, 38, 41, 45, 47, 52, 58] plt.hist(ages, bins=[10, 20, 30, 40, 50, 60], edgecolor='black') plt.show() - 2 marks
What does
plt.savefig()do? Write the statement to save the current chart asresult.pdfin the folderD:/IP.Answersavefig() saves the current figure to a file; the format comes from the extension. It must be called before show().
plt.savefig('D:/IP/result.pdf') - 2 marks
Predict the number of bars and the height of each bar drawn by:
plt.hist([5, 15, 25, 35, 45], bins=[0, 20, 40, 60])AnswerThree bins: 0-20 has 5 and 15 (2 values), 20-40 has 25 and 35 (2 values), 40-60 has 45 (1 value). So there are 3 bars of heights 2, 2 and 1. Checking with Python:
Python import matplotlib.pyplot as plt counts, edges, bars = plt.hist([5, 15, 25, 35, 45], bins=[0, 20, 40, 60]) print(counts)Output[2. 2. 1.]
- 2 marks
A DataFrame
stockhas columnsItemandQty. Fill in the blanks to draw a horizontal bar chart of quantity for each item.stock.plot(kind=________, x=________, y='Qty')Answer'barh'and'Item':Python import pandas as pd import matplotlib.pyplot as plt stock = pd.DataFrame({'Item': ['Pen', 'Pencil', 'Eraser'], 'Qty': [120, 300, 90]}) stock.plot(kind='barh', x='Item', y='Qty') plt.show() - 2 marks
Name any four parameters of
plot()used to customise a line and state what each does.Answercolor: colour of the line, e.g.'green'.marker: symbol at each point, e.g.'o','*'.linestyle: pattern of the line, e.g.'--',':'.linewidth: thickness of the line, e.g.2.5.
(Also accepted:
markersize,label,markeredgecolor.) - 2 marks
Differentiate between
xlabel()andxticks()with an example of each.Answerxlabel()writes one name for the whole x-axis, e.g.plt.xlabel('Month').xticks()sets the positions and text of the individual tick marks along the x-axis, e.g.plt.xticks([1, 2, 3], ['Jan', 'Feb', 'Mar']). - 2 marks
What is the role of the
binsparameter inhist()? Explain the two ways it can be given.Answerbins decides the intervals into which the data is grouped.
- As an integer, e.g.
bins=4: four equal-width bins from the minimum to the maximum value. - As a list of edges, e.g.
bins=[0, 33, 60, 100]: bins 0-33, 33-60 and 60-100, which may be of unequal width. Each bin includes its left edge; the last bin also includes its right edge.
- As an integer, e.g.
Long answer
- 3 marks
Write a Python program to draw a bar graph showing the house-wise points of a school sports meet: Tagore 145, Raman 160, Shivaji 132, Ashoka 171. Give each bar a different colour, add a title and axis labels, and save the chart as
houses.png.AnswerProgram (savefig comes before show):
Python import matplotlib.pyplot as plt houses = ['Tagore', 'Raman', 'Shivaji', 'Ashoka'] points = [145, 160, 132, 171] plt.bar(houses, points, color=['red', 'blue', 'green', 'gold']) plt.title('Annual Sports Meet: House Points') plt.xlabel('House') plt.ylabel('Points') plt.savefig('houses.png') plt.show() - 3 marks
Fill in the five blanks so that the program plots the maximum temperatures of Delhi and Shimla for five days on the same chart, with markers, a legend and a grid.
import matplotlib.pyplot as pltdays = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri']delhi = [39, 41, 40, 42, 38]shimla = [24, 25, 23, 26, 22]plt.plot(days, delhi, marker='o', ________='Delhi')plt.plot(days, shimla, marker='s', label='Shimla')plt.________('Maximum temperature in May')plt.ylabel('Temperature (deg C)')plt.________()plt.________(True)plt.________()
AnswerBlanks:
label,title,legend,grid,show.Python import matplotlib.pyplot as plt days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri'] delhi = [39, 41, 40, 42, 38] shimla = [24, 25, 23, 26, 22] plt.plot(days, delhi, marker='o', label='Delhi') plt.plot(days, shimla, marker='s', label='Shimla') plt.title('Maximum temperature in May') plt.ylabel('Temperature (deg C)') plt.legend() plt.grid(True) plt.show() - 3 marks
Find and correct the errors in the following code. Rewrite the correct code and underline (mention) each correction.
import matplotlib.pyplot as plx = [1, 2, 3, 4]y = [10, 20, 15]plt.plot(x, y, colour='red')plt.title = 'Weekly sales'plt.show
AnswerCorrections: (1) alias must match its use, so
as plt; (2) x and y must be the same length, so add a fourth value to y; (3)colourmust becolor; (4)titleis a function, soplt.title('Weekly sales'); (5)showmust be called with brackets:plt.show().Python import matplotlib.pyplot as plt x = [1, 2, 3, 4] y = [10, 20, 15, 25] plt.plot(x, y, color='red') plt.title('Weekly sales') plt.show() - 3 marks
Explain the
histtypeandcumulativeparameters ofhist(). Write code that draws a cumulative, outline-only histogram of the listwt = [38, 41, 44, 45, 47, 49, 50, 52, 55, 58]using bins 35-40-45-50-55-60, and print the cumulative counts.Answerhisttypesets the drawing style:'bar'(filled bars, default),'barstacked'(stacked bars for several data sets),'step'(outline only) and'stepfilled'(filled outline).cumulative=Truemakes each bar count all values up to and including that bin, so the last bar equals the number of values.Bins: 35-40 has 38 (1); 40-45 has 41, 44 (2); 45-50 has 45, 47, 49 (3); 50-55 has 50, 52 (2); 55-60 has 55, 58 (2). Cumulative counts: 1, 3, 6, 8, 10.
Python import matplotlib.pyplot as plt wt = [38, 41, 44, 45, 47, 49, 50, 52, 55, 58] c, e, b = plt.hist(wt, bins=[35, 40, 45, 50, 55, 60], histtype='step', cumulative=True) print(c) plt.title('Weights of students (cumulative)') plt.xlabel('Weight (kg)') plt.ylabel('Number of students') plt.show()Output[ 1. 3. 6. 8. 10.]
- 5 marks
The file
sales.csvcontains quarterly sales (in lakh rupees) of a company's North and South regions, with columns Region, Quarter and Sales.Write a program to (a) read the file into a DataFrame, (b) arrange it so that each quarter is a row and each region a column, (c) draw a grouped bar chart with a title, axis labels and legend, and (d) save the chart as
quarterly.png. Also print the total sales of each region.Answerpivot()turns the long table into one row per quarter and one column per region.df.plot(kind='bar')then draws a pair of bars per quarter, and the legend is built from the column names North and South.Python import pandas as pd import matplotlib.pyplot as plt df = pd.read_csv('sales.csv') table = df.pivot(index='Quarter', columns='Region', values='Sales') print(table.sum()) table.plot(kind='bar', color=['teal', 'coral'], edgecolor='black') plt.title('Quarterly sales by region') plt.xlabel('Quarter') plt.ylabel('Sales (Rs lakh)') plt.xticks(rotation=0) plt.legend(title='Region') plt.savefig('quarterly.png') plt.show()OutputRegion North 1780 South 1710 dtype: int64
- 5 marks
Compare a line plot, a bar graph and a histogram: say when each is used and write one short pyplot statement for each. Then, for each situation below, name the best chart: (i) monthly electricity bill of a school for a year, (ii) number of medals won by five states, (iii) waiting times of 300 patients at a hospital.
Answer- Line plot: shows change over time or ordered data; points are joined.
plt.plot(months, bill) - Bar graph: compares separate categories; bars with gaps.
plt.bar(states, medals) - Histogram: shows how numeric data is spread over intervals; bars touch and heights are frequencies.
plt.hist(waiting, bins=10)
(i) Line plot, because the bill changes over time. (ii) Bar graph, because states are separate categories. (iii) Histogram, because waiting time is continuous data and we want its distribution.
- Line plot: shows change over time or ordered data; points are joined.
- 5 marks
Write a program that creates a DataFrame of five students (Name, Term1, Term2 marks out of 100), then draws (a) a line chart of both terms with markers and (b) a horizontal bar chart of Term2 marks, both from the DataFrame using
plot(kind=...). Add suitable titles and axis labels.AnswerOne possible program:
Python import pandas as pd import matplotlib.pyplot as plt df = pd.DataFrame({ 'Name': ['Arjun', 'Pooja', 'Kunal', 'Neha', 'Vikram'], 'Term1': [72, 85, 64, 90, 58], 'Term2': [78, 88, 70, 86, 66] }) df.plot(kind='line', x='Name', y=['Term1', 'Term2'], marker='o', title='Term-wise marks') plt.ylabel('Marks') plt.show() df.plot(kind='barh', x='Name', y='Term2', color='olive', legend=False, title='Term 2 marks') plt.xlabel('Marks') plt.show()
Case-based
The PT teacher of Kendriya Vidyalaya, Bhopal recorded the runs scored by two inter-house teams, Tigers and Eagles, in five matches:
- Matches: M1, M2, M3, M4, M5
- Tigers: 145, 162, 128, 171, 150
- Eagles: 138, 155, 149, 160, 166
Riya, a Class XII student, is writing a program to compare the two teams. Her incomplete code is:
import ________ as pltm = ['M1', 'M2', 'M3', 'M4', 'M5']t = [145, 162, 128, 171, 150]e = [138, 155, 149, 160, 166]plt.plot(m, t, 'bo-', label='Tigers')plt.plot(m, e, ________, label='Eagles')plt.________plt.________plt.show()
- 1 mark
Fill in line 1.
Answerimport matplotlib.pyplot as plt - 1 mark
Fill in line 6 so that the Eagles line is red, dashed, with star markers.
Answerplt.plot(m, e, 'r*--', label='Eagles') - 1 mark
Fill in lines 7 and 8 to add the title 'Tigers vs Eagles' and show the legend.
AnswerLine 7:
plt.title('Tigers vs Eagles'); line 8:plt.legend() - 1 mark
Riya wants to save the chart as
teams.png. Write the statement and say where it must be placed.Answerplt.savefig('teams.png')must be placed beforeplt.show(), i.e. between lines 8 and 9. Complete program:Python import matplotlib.pyplot as plt m = ['M1', 'M2', 'M3', 'M4', 'M5'] t = [145, 162, 128, 171, 150] e = [138, 155, 149, 160, 166] plt.plot(m, t, 'bo-', label='Tigers') plt.plot(m, e, 'r*--', label='Eagles') plt.title('Tigers vs Eagles') plt.legend() plt.savefig('teams.png') plt.show()
Gupta General Store, Lucknow keeps its weekly sales in a DataFrame shop:
- Columns: Day, Grocery, Dairy, Snacks
- Rows: Mon to Sat, values in rupees
The owner's son, Aditya, wants to use pandas plotting to present this to his father.
- 1 mark
Write the statement to draw a line chart of all three categories with Day on the x-axis.
Answershop.plot(kind='line', x='Day') - 1 mark
Write the statement to draw a grouped bar chart of only Dairy and Snacks, with the title 'Dairy vs Snacks'.
Answershop.plot(kind='bar', x='Day', y=['Dairy', 'Snacks'], title='Dairy vs Snacks') - 1 mark
Which
kindvalue draws a histogram of the Grocery column? Write the statement with 4 bins.Answerkind='hist':shop.plot(kind='hist', y='Grocery', bins=4) - 2 marks
Write the complete program for the bar chart, including the DataFrame creation (any sample values), a y-axis label and showing the plot.
AnswerSample program:
Python import pandas as pd import matplotlib.pyplot as plt shop = pd.DataFrame({ 'Day': ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], 'Grocery': [5200, 4800, 5100, 4900, 6100, 7800], 'Dairy': [2100, 2000, 2250, 1950, 2300, 2900], 'Snacks': [1500, 1350, 1600, 1400, 1900, 2600] }) shop.plot(kind='bar', x='Day', y=['Dairy', 'Snacks'], title='Dairy vs Snacks') plt.ylabel('Sales (Rs)') plt.show()
A school counsellor collected the number of hours of sleep of 16 Class X students on a school night:
sleep = [5, 5.5, 6, 6, 6.5, 6.5, 7, 7, 7, 7.5, 7.5, 8, 8, 8.5, 9, 9.5]
She wants a chart that shows how many students sleep 5-6, 6-7, 7-8, 8-9 and 9-10 hours.
- 1 mark
Which type of chart should she use, and why?
AnswerA histogram, because sleep hours are continuous numeric data and she wants the number of students in each interval (a frequency distribution).
- 1 mark
Write the
hist()statement with the required bins and black bar borders.Answerplt.hist(sleep, bins=[5, 6, 7, 8, 9, 10], edgecolor='black') - 1 mark
How many students fall in the 7-8 hour bin? Explain how a value of exactly 8 is treated.
AnswerThe 7-8 bin includes 7 but not 8, so it holds 7, 7, 7, 7.5, 7.5: 5 students. A value of 8 goes in the 8-9 bin. Verified:
Python import matplotlib.pyplot as plt sleep = [5, 5.5, 6, 6, 6.5, 6.5, 7, 7, 7, 7.5, 7.5, 8, 8, 8.5, 9, 9.5] c, e, b = plt.hist(sleep, bins=[5, 6, 7, 8, 9, 10], edgecolor='black') print(c)Output[2. 4. 5. 3. 2.]
- 1 mark
What change to the statement would make each bar show the number of students sleeping up to that many hours?
AnswerAdd
cumulative=True:plt.hist(sleep, bins=[5, 6, 7, 8, 9, 10], edgecolor='black', cumulative=True)
Practicals
1Subject-wise performance: line plot
Create a DataFrame of the marks of four students in five subjects. Draw a line plot with one line per student (subjects on the x-axis), using a different marker for each line. Add a title, axis labels, legend and grid.
import pandas as pd
import matplotlib.pyplot as plt
marks = pd.DataFrame({
'Ananya': [88, 92, 79, 85, 95],
'Bharat': [72, 65, 70, 68, 81],
'Charu': [91, 78, 84, 80, 87],
'Dev': [60, 74, 66, 71, 77]
}, index=['English', 'Maths', 'Physics', 'Chemistry', 'IP'])
print(marks)
styles = ['o', 's', '^', 'D']
for name, m in zip(marks.columns, styles):
plt.plot(marks.index, marks[name], marker=m, label=name)
plt.title('Subject-wise marks of four students')
plt.xlabel('Subject')
plt.ylabel('Marks')
plt.legend()
plt.grid(True)
plt.show()Ananya Bharat Charu Dev English 88 72 91 60 Maths 92 65 78 74 Physics 79 70 84 66 Chemistry 85 68 80 71 IP 95 81 87 77
Viva questions (3)
- Why is a legend needed here? There are four lines, and the legend tells which line belongs to which student.
- What does marker='s' draw? A square at each data point.
- What happens if plt.legend() is called but no label is given? No legend is drawn and Matplotlib shows a warning.
2Class-wise average: bar graph and savefig
The average IP marks of sections XII-A to XII-E are 74, 68, 81, 77 and 63. Draw a bar graph with bar width 0.5, a different colour for each bar and black edges. Add a title and labels, and save the chart as both PNG and PDF before displaying it.
import matplotlib.pyplot as plt
sec = ['XII-A', 'XII-B', 'XII-C', 'XII-D', 'XII-E']
avg = [74, 68, 81, 77, 63]
plt.bar(sec, avg, width=0.5, edgecolor='black',
color=['#4e79a7', '#f28e2b', '#59a14f', '#e15759', '#b07aa1'])
plt.title('Section-wise average in IP')
plt.xlabel('Section')
plt.ylabel('Average marks')
plt.savefig('section_avg.png')
plt.savefig('section_avg.pdf')
plt.show()Viva questions (3)
- What is the default bar width? 0.8.
- Why must savefig() come before show()? Closing the shown window clears the figure, so a later savefig() saves a blank image.
- How do you make the bars horizontal? Use plt.barh() with the values on the x-axis.
3Term 1 vs Term 2: grouped bar graph
Compare the Term 1 and Term 2 class averages in five subjects using a grouped (side-by-side) bar graph. Put subject names under each pair of bars and add a legend.
import matplotlib.pyplot as plt
import numpy as np
subjects = ['English', 'Maths', 'Physics', 'Chemistry', 'IP']
term1 = [70, 62, 58, 66, 78]
term2 = [74, 69, 63, 65, 84]
x = np.arange(len(subjects))
w = 0.4
plt.bar(x - w/2, term1, width=w, label='Term 1')
plt.bar(x + w/2, term2, width=w, label='Term 2')
plt.xticks(x, subjects)
plt.title('Class average: Term 1 vs Term 2')
plt.ylabel('Average marks')
plt.legend()
plt.show()
for s, a, b in zip(subjects, term1, term2):
print(f'{s:10s} change: {b - a:+d}')English change: +4 Maths change: +7 Physics change: +5 Chemistry change: -1 IP change: +6
Viva questions (3)
- Why are the x positions shifted by w/2? So that the two bars of each subject stand side by side instead of on top of each other.
- What does np.arange(5) give? The array [0 1 2 3 4].
- Which subject's average fell in Term 2? Chemistry, by 1 mark.
4Frequency distribution: histogram
The marks (out of 50) of 25 students in an IP unit test are given. Draw a histogram with bins of width 10 from 0 to 50, sky-blue bars with black edges, and print the frequency of each bin. Then draw a second, cumulative histogram using histtype='step'.
import matplotlib.pyplot as plt
marks = [12, 18, 22, 25, 27, 28, 30, 31, 31, 33, 34, 35, 36,
37, 38, 38, 40, 41, 42, 43, 44, 46, 47, 49, 50]
edges = [0, 10, 20, 30, 40, 50]
freq, b, p = plt.hist(marks, bins=edges, color='skyblue', edgecolor='black')
plt.title('IP unit test marks')
plt.xlabel('Marks (out of 50)')
plt.ylabel('Number of students')
plt.show()
for i in range(len(freq)):
print(f'{edges[i]}-{edges[i+1]}: {int(freq[i])}')
plt.hist(marks, bins=edges, cumulative=True, histtype='step', linewidth=2)
plt.title('Cumulative frequency')
plt.xlabel('Marks (out of 50)')
plt.ylabel('Students up to this mark')
plt.show()0-10: 0 10-20: 2 20-30: 4 30-40: 10 40-50: 9
Viva questions (3)
- In which bin is the mark 30 counted? In 30-40, because a bin includes its left edge.
- In which bin is the mark 50 counted? In 40-50, because the last bin includes both edges.
- What does the last bar of a cumulative histogram show? The total number of values, here 25.
5Aggregate and plot data from a CSV file
Read sales.csv (columns Region, Quarter, Sales). Use groupby to find the total sales of each region and the total for each quarter. Plot region totals as a horizontal bar chart and quarter totals as a line chart, each with a title.
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('sales.csv')
by_region = df.groupby('Region')['Sales'].sum()
by_quarter = df.groupby('Quarter')['Sales'].sum()
print(by_region)
print(by_quarter)
by_region.plot(kind='barh', color='darkcyan', title='Total sales by region')
plt.xlabel('Sales (Rs lakh)')
plt.show()
by_quarter.plot(kind='line', marker='o', color='maroon', title='Total sales by quarter')
plt.ylabel('Sales (Rs lakh)')
plt.show()Region North 1780 South 1710 Name: Sales, dtype: int64 Quarter Q1 800 Q2 870 Q3 840 Q4 980 Name: Sales, dtype: int64
Viva questions (3)
- Which function reads a CSV file into a DataFrame? pandas.read_csv().
- Why do we select ['Sales'] before sum()? So that only the numeric column is added, not the text columns.
- What is on the y-axis of the barh chart? The index of the Series, i.e. the region names.
6One DataFrame, many charts with df.plot(kind=...)
Create a DataFrame of daily AQI (air quality index) readings for two cities over seven days. Using only df.plot(), draw (a) a line plot with markers and a figure size of 9 x 4 inches, (b) a grouped bar chart, and (c) a histogram of one city's values with 4 bins and black edges.
import pandas as pd
import matplotlib.pyplot as plt
aqi = pd.DataFrame({
'Delhi': [312, 290, 335, 360, 298, 275, 320],
'Chennai': [72, 85, 64, 90, 78, 69, 81]
}, index=['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'])
print(aqi.describe().loc[['mean', 'min', 'max']])
aqi.plot(kind='line', marker='o', figsize=(9, 4), title='Daily AQI')
plt.ylabel('AQI')
plt.show()
aqi.plot(kind='bar', title='Daily AQI (bar)')
plt.ylabel('AQI')
plt.xticks(rotation=0)
plt.show()
aqi.plot(kind='hist', y='Delhi', bins=4, edgecolor='black', title='Delhi AQI spread')
plt.xlabel('AQI')
plt.show()Delhi Chennai mean 312.857143 77.0 min 275.000000 64.0 max 360.000000 90.0
Viva questions (3)
- Which kind is the default in df.plot()? 'line'.
- Where does the legend text come from in df.plot()? From the column names.
- Name two kinds of df.plot() that are outside the syllabus. 'pie' and 'scatter' (also 'box', 'area').
Common mistakes
Writing
plt.savefig()afterplt.show(). The figure is cleared when the window closes, so the saved file is blank. Always save first, then show.Using
colour=(British spelling) as a parameter. Matplotlib accepts onlycolor=(orc=) and raises an error forcolour.Calling
plt.legend()without givinglabel=to any plot. No legend is drawn and Matplotlib prints a warning (No artists with labels found to put in legend). Give eachplot()/bar()a label, or pass a list of names tolegend().Passing counts to
hist()instead of raw data, for exampleplt.hist([5, 8, 3])meaning "5 students, 8 students, 3 students".hist()counts the values itself; for ready-made counts usebar().Drawing a grouped bar chart with the same x positions for both
bar()calls, so one set of bars hides the other. Shift the positions by the bar width.Assigning instead of calling:
plt.title = 'Sales'replaces the function and no title appears. Writeplt.title('Sales').Lists of different lengths in
plt.plot(x, y). Python raises a ValueError; x and y must have the same number of values.Confusing
'b'(blue) with black, which is'k', and confusingxlabel()(axis name) withxticks()(labels on each tick).