Σήμερα ασχοληθήκαμε με την επεξεργασία των δεδομένων στο αρχείο ol.csv
(κατεβάστε το στον υπολογιστή σας αν θέλετε να τρέξετε τα κομμάτια του κώδικα που υπάρχουν σε αυτό το σημειωματάριο).
http://www.tableau.com/public/community/sample-data-sets
όπου μπορείτε να βρείτε και άλλα ενδιαφέροντα δεδομένα). Τα δεδομένα αφορούν τους Ολυμπιακούς αγώνες (από το 2000 έως το 2012) και τους αθλητές που έχουν πάρει μετάλλια σε αυτούς. Μπορείτε να δείτε τα περιεχόμενα του αρχείου κατάλληλα διαμορφωμένα
Περιέχει πάνω από 8000 γραμμές και σε κάθε γραμμή υπάρχει το όνομα ενός αθλητή και το πόσα (και τι) μετάλλια πήρε σε κάποια Ολυμπιάδα. Ο ίδιος αθλητής εμφανίζεται ενδεχομένως σε περισσότερες από μία γραμμές. Υπάρχουν συνολικά 10 πεδία σε κάθε γραμμή, τα οποία τα αριθμούμε από 0 έως 9.
Το αρχείο αυτό είναι ένα αρχείο κειμένου που περιέχει μια γραμμή κειμένου για κάθε γραμμή στη μορφή του πίνακα που φαίνεται πιο πάνω. Τα διάφορα πεδία στην κάθε γραμμή διαχωρίζονται με το σύμβολο του κόμμα (εξ ου και η κατάληξη csv, comma separated values). Ιδού μερικές πρώτες γραμμές του αρχείου:Athlete,Age,Country,Year,Closing Ceremony Date,Sport,Gold Medals,Silver Medals,Bronze Medals,Total Medals Michael Phelps,23,United States,2008,8/24/2008,Swimming,8,0,0,8 Michael Phelps,19,United States,2004,8/29/2004,Swimming,6,0,2,8 Michael Phelps,27,United States,2012,8/12/2012,Swimming,4,2,0,6 Natalie Coughlin,25,United States,2008,8/24/2008,Swimming,1,2,3,6 Aleksey Nemov,24,Russia,2000,10/1/2000,Gymnastics,2,1,3,6 Alicia Coutts,24,Australia,2012,8/12/2012,Swimming,1,3,1,5 Missy Franklin,17,United States,2012,8/12/2012,Swimming,4,0,1,5 Ryan Lochte,27,United States,2012,8/12/2012,Swimming,2,2,1,5 Allison Schmitt,22,United States,2012,8/12/2012,Swimming,3,1,1,5
Για να επεξεργαστούμε το αρχείο αυτό διαβάζουμε όλες τις γραμμές του με τη μέθοδο readlines()
, αφαιρούμε από κάθε γραμμή που διαβάσαμε το τελευταίο newline (με τη μέθοδο rstrip()
). Αυτό το τελευταίο επιτυγχάνεται με την εντολή lines = [x.rstrip() for x in lines]
και η λίστα lines
περιέχει πλέον ένα string για κάθε γραμμή του αρχείου, string από το οποίο έχει αφαιρεθεί το τελευταίο newline.
Με τη γραμμή lines.pop(0)
αφαιρούμε από τη λίστα αυτή το πρώτο της στοιχείο, μια και η πρώτη γραμμή του αρχείου μας περιέχει μόνο επικεφαλίδες και όχι πληροφορία για κάποιον αθλητή.
Τέλος με την εντολή lines[0:10]
τυπώνουμε την υπολίστα της lines
που αποτελείται από τα 10 πρώτα στοιχεία της.
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
lines = [x.rstrip() for x in lines]
lines.pop(0)
lines[0:10]
Εδώ βλέπουμε πώς χρησιμοποιείται η μέθοδος split
για να δημιουργήσουμε από το string μιας γραμμής μια λίστα από strings, τις λέξεις στις οποίες διασπάται η γραμμή αυτή αν θεωρήσουμε το ','
ως διαχωριστικό. Τη δοκιμάζουμε αυτή τη μέθοδο στο πρώτο string της λίστας lines
, στην πρώτη γραμμή του αρχείου δηλ. (πέρα από την επικεφαλίδα).
s = lines[0]
l = s.split(',')
print l
Στο επόμενο μετράμε το πόσοι συνολικά αθλητές αναφέρονται στο αρχείο αυτό, προσέχοντας να μετρήσουμε μόνο μια φορά τον καθένα. Χρησιμοποιούμε μια λίστα names
, αρχικά κενή, και διανύοντας της λίστα lines
, παίρνουμε από το κάθε στοιχείο της το όνομα του αθλητή με την εντολή nm = s.split(',')[0]
(σπάμε το string s
με διαχωριστικό το κόμμα σε μια λίστα από λέξεις και παίρνουμε την πρώτη με το [0]
). Αν το όνομα nm
δεν υπάρχει ήδη στη λίστα names
τότε απλά το προσθέτουμε με την εντολή names.append(nm)
.
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
lines = [x.rstrip() for x in lines]
lines.pop(0)
names = []
for s in lines:
nm = s.split(',')[0]
if not(nm in names):
names.append(nm)
print "Number of atheletes is {n}".format(n=len(names))
Στο επόμενο ψάχνουμε να βρούμε ποιος είναι ο αθλητής που έχει μαζέψει τα περισσότερα μετάλλια (όλων των ειδών).
Χρησιμοποιούμρ γι' αυτό ένα λεξικό (dictionary) με όνομα medals
, αρχικά κενό, στο οποίο αποθηκεύουμε το πλήθος των μεταλίων του κάθε ατόμου. Τα στοιχεία δηλαδή του λεξικού αυτού είναι της μορφής name: number-of-medals
. Στο πρώτο for
loop που έχουμε περνάμε κάθε γραμμή του αρχείου, παίρνουμε το όνομα που της αντιστοιχεί στη μεταβλητή nm
και το πλήθος των μεταλίων που της αντιστοιχούν στη μεταβλητή md
και, αν υπάρχει ήδη καταχώρηση για το nm
στο λεξικό τότε απλά την επαυξάνουμε κατά md
, ενώ αν δεν υπάρχει ήδη καταχώρηση τότε καταχωρούμε για πρώτη φορά το κλειδί nm
με τιμή ίση με md
.
Στο τελευταίο loop διανύουμε το λεξικό medals
για να βρούμε το άτομο (για την ακρίβεια, ένα από τα άτομα) με τα περισσότερα μετάλλια. Στη μεταβλητή m
κρατάμε το τρέχον μέγιστο και στη μεταβλητή who
κρατάμε τον τρέχοντα αθλητή με το μεγαλύτερο όνομα.
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
lines = [x.rstrip() for x in lines]
lines.pop(0)
medals = {}
for s in lines:
l = s.split(',')
nm = l[0]
md = int(l[9])
if nm in medals:
medals[nm] += md
else:
medals[nm] = md
m = 0
who = ""
for n in medals:
if medals[n] > m:
m = medals[n]
who = n
print "{n} has {m} medals".fol = [ [1, 2, 0], [0, 2], [1.1, 2, 3, 4], [10] ]
def g(x):
return sum(x)
l.sort(key=g)
lrmat(n=who, m=m)
Αν έχουμε μια λίστα αριθμών, π.χ. L = [1, 3.2, -1]
και καλέσουμε τη μέθοδο sort
τότε η λίστα ταξινομείται κατά αύξουσα σειρά.
L = [1, 3.2, -1]
L.sort()
Ll = [ [1, 2, 0], [0, 2], [1.1, 2, 3, 4], [10] ]
def g(x):
return sum(x)
l.sort(key=g)
l
Αν τα αντικείμενα που περιέχονται στη λίστα είναι πιο πολύπλοκα από αριθμοί (ή αν το κριτήριό μας είναι διαφορετικό) τότε θα πρέπει να πούμε στη μέθοδο sort
το πώς θέλουμε να ταξινομηθεί η λίστα. Αυτό γίνεται ως εξής. Ορίζουμε μια συνάρτηση αξίας του κάθε αντικειμένου και ζητάμε η ταξινόμηση να γίνει με αύξουσα σειρά της αξίας των αντικειμένων της λίστας. Τη συνάρτηση αυτή την περνάμε ως παράμετρο με το όνομα key
στη μέθοδο sort
.
Στο παρακάτω παράδειγμα έχουμε μια λίστα l
που τα στοιχεία της είναι ζεύγη αριθμών. Θέλουμε να διατάξουμε τη λίστα αυτή κατ' αύξουσα σειρά με βάση το δεύτερο στοιχείο του κάθε ζεύγους.
Ορίζουμε τη συνάρτηση f(x)
να επιστρέφει x[1]
, δηλώνοντας έτσι ότι η αξία του ζεύγους x
είναι η δεύτερή του θέση x[1]
. Έπειτα καλούμε τη μέθοδο sort
για τη λίστα l
δίνοντας ως παράμετρο με όνομα key
το όνομα της συνάρτησης f
.
l = [ [0, 1], [1, 3], [-1, 2] ]
def f(x):
return x[1]
l.sort(key=f)
l
Στο επόμενο παράδειγμα έχουμε μια λίστα l
η οποία περιέχει λίστες αριθμών, όχι απαραίτητα όλες του ίδιου μήκους. Θέλουμε να διατάξουμε την l
με αύξουσα σειρά του αθροίσματος των στοιχείων του κάθε αντικειμένου της l
.
Ορίζουμε έτσι τη συνάρτηση αξίας g
να επιστρέφει το άθροισμα των στοιχείων του ορίσματός της (το οποίο θα είναι μια λίστα αριθμών, γιατί τέτοια είναι τα στοιχεία της l
). Έπειτα καλούμε τη sort
με key
αυτή τη συνάρτηση.
l = [ [1, 2, 0], [0, 2], [1.1, 2, 3, 4], [10] ]
def g(x):
return sum(x)
l.sort(key=g)
l
Πώς μπορούμε να τροποποιήσουμε το πρόγραμμα που γράψαμε παραπάνω το οποίο έβρισκε τον αθλητή με τα περισσότερα μετάλλια ώστε να μη βρίσκει μόνο τον πρώτο αλλά να μας βγάζει όλους τους αθλητές σε φθίνουσα σειρά συνολικών μεταλλίων;
Έχοντας υπολογίσει το λεξικό medals
θα πρέπει κατ' αρχήν να μεταβιβάσουμε τα περιεχόμενά του σε μια λίστα μια και τα λεξικά δεν ταξινομούνται. Δημιουργούμε λοιπόν τη λίστα L
η οποία περιέχει για κάθε όνομα x
στο medals
ένα ζεύγος με το όνομα και τα μετάλλιά του.
Ορίζουμε έπειτα τη συνάρτηση f
ώστε να διατάξουμε τα ζεύγη αυτά με φθίνουσα σειρά (γι' αυτό το πρόσημο μείον) του δεύτερου στοιχείου τους και καλούμε τη μέθοδο L.sort
. Δείχνουμε στο τέλος τα 20 πρώτα στοιχεία της L
.
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
lines = [x.rstrip() for x in lines]
lines.pop(0)
medals = {}
for s in lines:
l = s.split(',')
nm = l[0]
md = int(l[9])
if nm in medals:
medals[nm] += md
else:
medals[nm] = md
L = [[x, medals[x]] for x in medals]
def f(x):
return -x[1]
L.sort(key=f)
L[0:20]
Αν τώρα θέλουμε να κάνουμε το ίδιο αλλά με χώρες και όχι με αθλητές (να διατάξουμε δηλ. τις χώρες κατά φθίνουσα σειρά των συνολικών μεταλλίων τους) το μόνο που έχουμε να κάνουμε στον παραπάνω κώδικα είναι να αλλάξουμε τη γραμμή nm = l[0]
μέσα στο πρώτο loop σε nm = l[2]
, χρησιμοποιώτας έτσι ως κλειδί στο λεξικό το όνομα της χώρας (που βρίσκεται στη θέση 2 σε κάθε γραμμή).
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
lines = [x.rstrip() for x in lines]
lines.pop(0)
medals = {}
for s in lines:
l = s.split(',')
nm = l[2]
md = int(l[9])
if nm in medals:
medals[nm] += md
else:
medals[nm] = md
L = [[x, medals[x]] for x in medals]
def f(x):
return -x[1]
L.sort(key=f)
L[0:20]
Τώρα θέλουμε να βρούμε ποιες είναι οι χώρες με τα μετάλλια στα περισσότερα διαφορετικά αγωνίσματα.
Χρησιμοποιούμε και πάλι ένα λεξικό cd
, αρχικά κενό, και κάθε φορά που συναντάμε μια χώρα κοιτάμε αν υπάρχει ήδη μέσα στο λεξικό. Αν υπάρχει τότε στη λίστα των αγωνισμάτων της προσθέτουμε το νέο αγώνισμα αν δεν υπάρχει ήδη. Αν η χώρα δεν υπάρχει τη βάζουμε μέσα στο λεξικό. Τέλος ταξινομούμε τη λίστα (στην οποία βάζουμε τα περιεχόμενα του λεξικού) κατά φθίνουσα σειρά του μήκους της λίστας των αγωνισμάτων.
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
lines = [x.rstrip() for x in lines]
lines.pop(0)
cd = {}
for s in lines:
l = s.split(',')
nm = l[2] # Όνομα χώρας
sport = l[5] # Όνομα αθλήματος
if nm in cd: # αν η χώρα είναι ήδη μέσα στο λεξικό
if not( sport in cd[nm] ): # αν το άθλημα δεν είναι ήδη στη λίστα αθλημάτων της χώρας
cd[nm].append(sport) # το βάζουμε μέσα
else:
cd[nm] = [ sport ] # αν η χώρα δεν είναι στο λεξικό τη βάζουμε με λίστα αθλημάτων να έχει μέσα μόνο το άθλημα αυτό.
L = [ [x, cd[x]] for x in cd ] # βάζουμε τα περιεχόμενα του λεξικού σε μια λίστα για ταξινόμηση
def f(l):
return -len(l[1]) # θέλουμε φθίνουσα κατάταξη κατά το μήκος της λίστας αθλημάτων
L.sort(key=f) # ταξινομούμε
LL = [[x[0], len(x[1]), x[1]] for x in L] # δημιουργούμε μια άλλη λίστα από την L που να περιέχει και το πλήθος των
# πέρα από τα ίδια τα αθλήματα
LL[0:5] # δείχνουμε τις 5 πρώτες χώρες
Στο επόμενο θέλουμε να βρούμε τις χώρες με τα περισσότερα μετάλλια συνολικά.
lines = [x.rstrip() for x in lines]
lines.pop(0)
medals = {}
for s in lines:
l = s.split(',')
nm = l[2]
md = int(l[9])
if nm in medals:
medals[nm] += md
else:
medals[nm] = md
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
lines = [x.rstrip() for x in lines]
lines.pop(0)
cd = {}
for s in lines:
l = s.split(',')
nm = l[2] # χώρα
athlete = l[0] # αθλητής
if nm in cd:
if not( athlete in cd[nm] ): # αν δεν είναι η αθλητής στη λίστα της χώρας τότε τον βάζουμε
cd[nm].append(athlete)
else:
cd[nm] = [ athlete ]
L = [ [x, cd[x]] for x in cd ]
def f(l):
return -len(l[1]) # ταξινομούμε κατά φθίνουσα σειρά μήκους λίστας αθλητών
L.sort(key=f)
LL = [[x[0], len(x[1])] for x in L]
LL[0:20]
L = [[x, medals[x]] for x in medals]
def f(x):
return -x[1]
L.sort(key=f)
L[0:20]
Εδώ βρίσκουμε τις χώρες με τους περισσότερους ολυμπιονίκες.
Στο λεξικό που έχει ως κλειδιά τις χώρες κρατάμε για κάθε χώρα μια λίστα με τα ονόματα των αθλητών της.
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
f = open("ol.csv", "r")
lines = f.readlines()
f.close()
lines = [x.rstrip() for x in lines]
lines.pop(0)
cd = {}
for s in lines:
l = s.split(',')
nm = l[2] # χώρα
athlete = l[0] # αθλητής
if nm in cd:
if not( athlete in cd[nm] ): # αν δεν είναι η αθλητής στη λίστα της χώρας τότε τον βάζουμε
cd[nm].append(athlete)
else:
cd[nm] = [ athlete ]
L = [ [x, cd[x]] for x in cd ]
def f(l):
return -len(l[1]) # ταξινομούμε κατά φθίνουσα σειρά μήκους λίστας αθλητών
L.sort(key=f)
LL = [[x[0], len(x[1])] for x in L]
LL[0:20]
Εδώ βλέπουμε πόσοι και ποιοι είναι οι αθλητές της Ελλάδας.
cd['Greece'], len(cd['Greece'])