2

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) 
Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
tom smith
  • 71
  • 3
  • 11
  • 1
    You need to post some code, as well as a more specific question - is there an error? What are you seeing that doesn't match your expectations? – thegrinner Nov 08 '12 at 21:52
  • 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) – tom smith Nov 08 '12 at 22:00
  • thats my code so far ad im wondering how to disply the data from grades list into a histogram in quickdraw – tom smith Nov 08 '12 at 22:01
  • Edit your question and include your code there (indented properly so it shows up as code) – Gerrat Nov 08 '12 at 22:03
  • I added the code to help you but modify it as appropriate. – r_31415 Nov 08 '12 at 22:05
  • where did you add it???? – tom smith Nov 08 '12 at 22:07
  • At the botton of the text. You need to accept the edit. – r_31415 Nov 08 '12 at 22:08
  • thanks so do you know how to use the data from the grades list and plot a histogram – tom smith Nov 08 '12 at 22:10
  • Why would you want to use quickdraw and not a python library for plotting graphs? – Chris Seymour Nov 08 '12 at 22:50

2 Answers2

9

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).

Chris Seymour
  • 83,387
  • 30
  • 160
  • 202
0

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.

r_31415
  • 8,752
  • 17
  • 74
  • 121
  • this is for an assignment in class so were not allowed to use matplotlib and we havent done arrays yet so not sure how that works – tom smith Nov 09 '12 at 00:24
  • Oh, sorry. I missed the part of quickdraw. – r_31415 Nov 09 '12 at 01:30
  • Sorry. I can't help you with quickdraw. – r_31415 Nov 09 '12 at 01:53
  • 1
    This is a very disjointed way to do it, why bother with python at all then? Piping the output of python into in `jar` that doesn't even support plotting graphs natively is very strange. If you haven't covered `arrays/lists` yet then how are you storing the column A1? I don't know what school or grade this for but if I was you I would go back with *sane* solution (or multiple sane solutions) and tell your teacher I researched the way you asked, my conclusion was it's a stupid method, here a `X` better ways to do it. – Chris Seymour Nov 09 '12 at 08:31
  • 1
    @RobertSmith I suppose you are right, thank good those days are over [for me]. The problem was bugging me so I coded something up quick. Check my edit if you are interested. – Chris Seymour Nov 09 '12 at 20:10
  • 1
    And for me :-) I liked very much your answer +1 I didn't even know what was quickdraw! – r_31415 Nov 09 '12 at 20:17