Question

I need help writing a program that reads about 300 lines from a text file and takes the grades from a specific assignment (column A1) and then uses the grades from that assignment to plot a histogram in quickdraw.

ID , Last,  First, Lecture, Tutorial, A1, A2, A3, A4, A5
8959079, Moore, Maria, L01, T03, 9.0, 8.5, 8.5, 10.0, 8.5
4295498, Taylor, John, L00, T04, 10.0, 6.5, 8.5, 9.5, 7.0
9326386, Taylor, David, L00, T00, 9.5, 8.0, 8.0, 9.0, 10.0
7223234, Taylor, James, L01, T03, 8.5, 5.5, 10.0, 0.0, 0.5
7547838, Miller, Robert, L01, T09, 7.0, 8.0, 8.5, 10.0, 0.5
0313453, Lee, James, L01, T01, 10.0, 0.5, 8.0, 7.0, 5.0
3544072, Lee, Helen, L00, T03, 10.0, 9.0, 7.0, 9.0, 8.5

So far I have a code that extracts the grades from the file(A1) and puts it into a list and then creates another that counts how many occurrences of a certain grade occur. I am having trouble now using this list and inputing it into quickdraw to plot a histogram?

def file(): 
  file = open('sample_input_1.txt', 'r') 
  col = [] data = file.readlines() 
  for i in range(1,len(data)-1): 
    col.append(int(float(data[i].split(',')[5]))) 
  return col 

def hist(col):   
  grades = [] 
  for i in range(11): 
    grades.append(0) 
  for i in (col): 
    grades[i] += 1   
  return grades 

col = file() 
grades = hist(col) 
print(col) 
print(grades) 

No correct solution

OTHER TIPS

Quickdraw doesn't support drawing graphs out of the box, All the rectangles, the grid, the text has to be mapped yourself. A much better way is to used python library that already exist. Don't try to reinvent the wheel.

Example 1 Quickdraw Solution

#!/bin/python 

# Quickdraw histogram: 
# Assume max grade is 10

A1 = [9.0,10.0,9.5,8.5,7.0,10.0,10.0]

histogram = []
for i in sorted(set(A1)): histogram.append([int(i*50),A1.count(i)])

gridsize = 500
griddiv = 20
topleft = 50

#graph title
print 'text', '"','Histogram of Grades','"', 220, 25

#x axis title
for i in range(1,21):
    print 'text', '"',float(i)/2,'"', (i+1)*25, 570

#y axix title
for i in range(0,11):
    print 'text', '"',i,'"', 25, 600-(i+1)*50

#grid
print 'grid', topleft, topleft, gridsize, gridsize, griddiv, griddiv

#chart rectangles 
print 'color 140 0 0'
for i in histogram:
    print 'fillrect',i[0]-25+topleft, gridsize-(50*i[1])+topleft,gridsize/griddiv,50*i[1],'b'+str(i[0])
    print 'fillrect', 'color','b'+str(i[0])

Here is what the graph looks like after running histogram.py | java -jar quickdraw.jar it's not pretty!

enter image description here

This solution really is horrible. The code is inherently messy (there is certainly a lot I could have done to improve both the readability and flexibility but it proves the concept anyway). Scaling isn't handle, which you will need as with 300 students records the count per grade will be greater than 10. Not to mention it looks horrible. It could be improved, for instance by drawing white lines round each rectangle would be a small improvement but you would need to do all the calculations.


Example 2 MATPLOTLIB Solution

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.mlab as mlab

# You already have A1 from the file in a list like this:
A1 = [9.0,10.0,9.5,8.5,7.0,10.0,10.0]

#Set up infomation about histogram and plot using A1
fig = plt.figure()
ax = fig.add_subplot(111)
ax.hist(A1, 12,facecolor='red')
ax.set_title('Grade Histogram')
ax.set_xlabel('Grade')
ax.set_ylabel('Count')
ax.set_xlim(min(A1)-0.5, max(A1)+0.5)
ax.set_ylim(0, max([A1.count(i) for i in sorted(set(A1))])+0.5)
ax.grid(True)
plt.show()

Output:

enter image description here

This is the best solution, the scaling is handled and graph looks excellent.


Example 3 Simple CLI

I would even take a step back and do a simple CLI version, don't try and run before you can't walk.

A1 = [9.0,10.0,9.5,8.5,7.0,10.0,10.0]

upper =2*int(max(A1))+1
lower =2*int(min(A1))-1

for i in [x * 0.5 for x in range(lower,upper)]:
    print i,'\t|' ,'*'*A1.count(i)

Output:

Grade Histogram
6.5     | 
7.0     | *
7.5     | 
8.0     | 
8.5     | *
9.0     | *
9.5     | *
10.0    | ***

This solution is a great start for beginner programmers! It's simple, clean and even scaling shouldn't be an issues (just increase the width of the terminal window if the bars get to long).

What about this to get you going?

s = """ID , Last,  First, Lecture, Tutorial, A1, A2, A3, A4, A5
8959079, Moore, Maria, L01, T03, 9.0, 8.5, 8.5, 10.0, 8.5
4295498, Taylor, John, L00, T04, 10.0, 6.5, 8.5, 9.5, 7.0
9326386, Taylor, David, L00, T00, 9.5, 8.0, 8.0, 9.0, 10.0
7223234, Taylor, James, L01, T03, 8.5, 5.5, 10.0, 0.0, 0.5
7547838, Miller, Robert, L01, T09, 7.0, 8.0, 8.5, 10.0, 0.5
0313453, Lee, James, L01, T01, 10.0, 0.5, 8.0, 7.0, 5.0
3544072, Lee, Helen, L00, T03, 10.0, 9.0, 7.0, 9.0, 8.5"""

from StringIO import StringIO

c = StringIO(s)
a = loadtxt(c, delimiter=',', dtype='S8')
A1 = a[1:, 5].astype('float32')
print A1
hist(A1, bins=10)

Output:

[  9.   10.    9.5   8.5   7.   10.   10. ]
Out[81]:
(array([1, 0, 0, 0, 0, 1, 1, 0, 1, 3]),
 array([  7. ,   7.3,   7.6,   7.9,   8.2,   8.5,   8.8,   9.1,   9.4,
         9.7,  10. ]),

enter image description here

The first list is the output of A1 in which I did a bit of processing to pass floats to hist. hist is a matplotlib function that prints histogram values and edges respectively.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top