Silverthorn Silverthorn - 12 days ago 5
Python Question

Plotting grades against assignment number

I want to do a plot in Python3 that will show me the assignments on the x-axis and the grades on the y-axis. The x-axis must show all assignments from 1 to M, and the y-axis must show all grades 3 to 12.

Input is a matrix of grades for M assignments: e.g. for 6 Assignments I have the following input:

array([[10, -3, 10, ..., 7, 0, 12],
[12, 12, 12, ..., 10, 0, 12],
[7, 7, 10, ..., 10, 0, 10],
[7, 4, 7, ..., 7, 0, 12],
[-3, 4, 7, ..., 4, 4, 12],
[7, 4, 4, ..., 4, 0, 12]], dtype=object)



  • First row - assignment 1 grades

  • Second row - assignment 2 grades

  • etc.



The plot must also contain:


  1. Each of the given grades marked by a dot. I need to add a small random
    number (between -0.1 and 0.1) to the x- and y-coordinates of each dot, to
    be able tell apart the different dots which otherwise would be on top of each
    other when more than one student has received the same grade in the same
    assignment.

  2. The average grade of each of the assignments plotted as a line.



I have started by trying with a for loop to plot each assignment, but it does not seem to work - therefore I am stuck at the moment.

import matplotlib.pyplot as plt
yaxis = np.arange(-3, 13)
for i in range(len(assignments)-1):
plt.plot(assignments[i, :], yaxis, label = "Assignemnt [i]")

plt.title("Grades per assignment")
plt.xlabel("Assignments")
plt.ylabel("Grades")
plt.show()

Answer

If I understood your question, this is what you want? Not sure how you want the average grade to be represented, but I left it as an exercise for you.

EDIT

For each call of plot() you have to have an x array and a y array that are the same dimensions. Here, I iterate over the data array, one row at a time using enumerate(), which returns an index, which I called a, and the row, which I called grades. There are 6 rows, so a will successively take the values 0,1,2,3,4,5,6.

Then, since you want to plot each grade against the assignment number a, you'd be tempted to do plot(a, grades). But, since x and y need to have the same dimension, we need to generate an array that has the same dimension as grades, which is what x = a*np.ones(len(grades)) does. From there, you could do plot(x, grades). But then, equal grades would overlap, as you pointed out in your question.

To avoid the overlap, I add a random number between [-0.1, 0.1) using the formula (jitter_max-jitter_min)*np.random.random(size=len(grades))+jitter_min (see the documentation for np.random.random()).

To plot the average, you simply need to calculate the average row-by-row, store that value in an array, then plot that array against an array of same dimension containing the assignment number (0,1,2,3,...). To plot it as a line, instead of simply points, check outthe documentation for plot: plot(..., ..., 'o-')

data = np.array([[10, -3, 10, 7, 0, 12],
   [12, 12, 12, 10, 0, 12],
   [7, 7, 10, 10, 0, 10],
   [7, 4, 7, 7, 0, 12],
   [-3, 4, 7, 4, 4, 12],
   [7, 4, 4, 4, 0, 12]])

jitter_min = -0.1
jitter_max = 0.1
for a,grades in enumerate(data):
    x = a*np.ones(len(grades)) + (jitter_max-jitter_min)*np.random.random(size=len(grades))+jitter_min
    plt.plot(x, grades, 'o', label='Assignment #{:d}'.format(a), clip_on=False)
plt.xlabel('Assignments')
plt.ylabel('Grades')

enter image description here

Comments