Ένας διαδραστικός οδηγός για την τάξη και το σπίτι, σε 8 βήματα. Η NumPy κάνει υπολογισμούς σε ολόκληρες συλλογές τιμών με μία γραμμή· στο τέλος (βήματα 5–6) βλέπουμε και τι κάνει «από κάτω», με δύο εργαλεία της βασικής Python: if και for. Ο κώδικας τρέχει μέσα στον browser σου: άλλαξέ τον, πάτησε Τρέξε (ή Ctrl+Enter) και δες τι γίνεται. Την πρώτη φορά που θα τρέξεις κώδικα με NumPy θα αργήσει λίγα δευτερόλεπτα να φορτώσει.
Οι λίστες της Python δεν ξέρουν μαθηματικά: prices * 2 επαναλαμβάνει τη λίστα και prices * 1.24 δίνει σφάλμα. Δοκίμασέ το:
Ο μόνος τρόπος με λίστες είναι ο κουραστικός: μια επανάληψη που περνά από κάθε στοιχείο (θα δούμε τον βρόχο for αναλυτικά στο βήμα 6· εδώ απλώς παρατήρησε πόσες γραμμές χρειάζεται).
Η NumPy (Numeric Python) προσφέρει έναν νέο τύπο, τον πίνακα (ndarray), που φτιάχνεται από μια λίστα με np.array(). Οι πράξεις εφαρμόζονται σε κάθε στοιχείο ξεχωριστά (element-wise), χωρίς βρόχο.
Πράξη ανάμεσα σε δύο πίνακες ίδιου μήκους γίνεται στοιχείο προς στοιχείο: πρώτο με πρώτο, δεύτερο με δεύτερο. Έτσι υπολογίζουμε π.χ. τα έσοδα ανά προϊόν.
Σε αντίθεση με τη λίστα, ο πίνακας NumPy περιέχει στοιχεία ενός μόνο τύπου. Αν δώσεις μείγμα, η NumPy τα μετατρέπει όλα στον «ευρύτερο» τύπο. Το .dtype σου λέει ποιον. Αυτό είναι που κάνει τις πράξεις γρήγορες, και είναι ο λόγος που για πραγματικούς πίνακες δεδομένων (με κείμενο και αριθμούς) θα χρειαστούμε το pandas την επόμενη εβδομάδα.
+ σε λίστες ενώνει, σε πίνακες NumPy προσθέτει. Ίδιο σύμβολο, άλλος τύπος, άλλη συμπεριφορά, όπως είδαμε και με τα strings. Το type() παραμένει ο πρώτος σου φίλος.Κέρδος ανά προϊόν με πράξεις ανάμεσα σε πίνακες, και συνολικό κέρδος. Θυμήσου: με λίστες η αφαίρεση δεν δουλεύει καν.
Δείκτες και slicing δουλεύουν ακριβώς όπως στις λίστες: sales[0], sales[-1], sales[:3], sales[6:]. Το καινούργιο είναι ότι μια σύγκριση σε πίνακα δίνει πίνακα από True/False, και αυτόν τον πίνακα μπορείς να τον βάλεις μέσα στις αγκύλες για να κρατήσεις μόνο τα στοιχεία όπου είναι True.
Πληκτρολόγησε μια συνθήκη και δες ποια στοιχεία «περνούν» το φίλτρο. Δοκίμασε x > 1500, x <= 1200, x == 1800, (x > 1500) & (x < 2000), (x < 1200) | (x > 2200):
Αφού το True μετρά ως 1: np.sum(sales > 1500) είναι πόσοι μήνες ξεπέρασαν το 1500 και np.mean(sales > 1500) το ποσοστό τους. Στο βήμα 6 θα δεις ότι «από κάτω» αυτό είναι ένας βρόχος με ένα if και έναν μετρητή· εδώ είναι μία γραμμή.
and / or της Python δουλεύουν με ένα True/False, όχι με πίνακα. Γράψε sales[sales > 1500 and sales < 2000] παραπάνω: θα πάρεις ValueError: The truth value of an array ... is ambiguous. Σε πίνακες χρησιμοποίησε & και | με παρενθέσεις γύρω από κάθε συνθήκη, ή np.logical_and() / np.logical_or().Το πιο χρήσιμο κόλπο της εβδομάδας: φίλτρο που φτιάχνεται από έναν πίνακα (sales) και εφαρμόζεται σε άλλον (months). Δουλεύει γιατί έχουν το ίδιο μήκος και την ίδια σειρά.
Η NumPy έχει έτοιμες συναρτήσεις για ό,τι θα υπολόγιζες με βρόχο: np.sum(), np.mean() (μέσος όρος), np.median() (διάμεσος), np.min(), np.max(), np.std() (τυπική απόκλιση). Η np.argmax() δίνει τη θέση του μεγίστου, κάτι πολύ χρήσιμο όταν έχεις έναν δεύτερο πίνακα με ονόματα.
Ο μέσος όρος επηρεάζεται πολύ από ακραίες τιμές (outliers). Η διάμεσος, δηλαδή η μεσαία τιμή όταν τα ταξινομήσεις, όχι. Μία τεράστια εταιρική παραγγελία αρκεί για να «ξεγελάσει» τον μέσο όρο:
np.corrcoef() επιστρέφει πίνακα 2×2· η τιμή εκτός διαγωνίου (0.957) είναι ο συντελεστής συσχέτισης: κοντά στο 1 σημαίνει «ανεβαίνουν μαζί», κοντά στο -1 «αντίθετα», κοντά στο 0 «καμία γραμμική σχέση». Συσχέτιση δεν σημαίνει αιτιότητα.Τέσσερις ερωτήσεις του διευθυντή, τέσσερις γραμμές NumPy. Κράτα τον κώδικα: στο βήμα 6 θα τον ξαναγράψεις με βρόχο για να δεις τι κάνει η NumPy από κάτω.
Από λίστα από λίστες φτιάχνεται πίνακας με γραμμές και στήλες: ένας μικρός πίνακας δεδομένων. Το .shape δίνει (γραμμές, στήλες). Εδώ: κάθε γραμμή ένα προϊόν, στήλη 0 η τιμή, στήλη 1 η ποσότητα.
Η επιλογή γίνεται με [γραμμή, στήλη], και σε κάθε θέση μπορείς να βάλεις δείκτη ή slice. Το : μόνο του σημαίνει «όλα». Δοκίμασε x[0], x[0, 1], x[:, 0], x[1:3, 1], x[-1, :]:
Το catalog[:, 0] είναι ένας κανονικός 1D πίνακας (όλες οι τιμές), άρα όλα όσα έμαθες ισχύουν. Οι συναρτήσεις όπως np.sum() και np.mean() δέχονται και όρισμα axis: axis=0 σημαίνει «κατά μήκος των γραμμών», δηλαδή ένα αποτέλεσμα ανά στήλη, και axis=1 ένα αποτέλεσμα ανά γραμμή.
Η Άσκηση 1 ξανά, αλλά τα δεδομένα είναι τώρα σε έναν 2D πίνακα, όπως θα έρχονται από ένα αρχείο. Πρώτα «κόβεις» στήλες, μετά υπολογίζεις.
Τα δύο τελευταία βήματα κοιτούν «κάτω από το καπό» της NumPy: πώς θα έκανες τα ίδια με τη βασική Python. Μέχρι τώρα ο κώδικας έτρεχε γραμμή-γραμμή, πάντα όλος. Με το if λέμε «αν ισχύει αυτό, κάνε εκείνο». Η συνθήκη είναι μια έκφραση που δίνει True ή False (οι συγκρίσεις της εβδομάδας 3). Μετά τη συνθήκη μπαίνει άνω-κάτω τελεία και οι γραμμές που «ανήκουν» στο if γράφονται με εσοχή (indentation), συνήθως 4 κενά.
Με elif (else if) ελέγχουμε περισσότερες περιπτώσεις με τη σειρά. Η Python εκτελεί το πρώτο μπλοκ που ταιριάζει και αγνοεί τα υπόλοιπα.
order = 500: ταιριάζουν και οι δύο πρώτες συνθήκες, αλλά εκτελείται μόνο η πρώτη. Μετά σβήσε την εσοχή μπροστά από το discount = 0.10 και διάβασε το σφάλμα (IndentationError).Γράψε τους τρεις κανόνες έκπτωσης με if / elif / else και τύπωσε Έκπτωση: 10%. Άλλαξε μετά το order σε 150 και 320 για να δεις ότι δουλεύει και στις άλλες περιπτώσεις.
Ο βρόχος for εκτελεί το ίδιο μπλοκ κώδικα για κάθε στοιχείο μιας λίστας. Σε κάθε γύρο η μεταβλητή (εδώ s) παίρνει το επόμενο στοιχείο. Και εδώ: άνω-κάτω τελεία και εσοχή.
Πολύ συχνά θέλουμε να μαζέψουμε κάτι μέσα στον βρόχο: ένα σύνολο, ένα πλήθος. Ξεκινάμε μια μεταβλητή από το 0 και την ενημερώνουμε σε κάθε γύρο. Συνδυάζοντας for με if μετράμε πόσα στοιχεία ικανοποιούν μια συνθήκη.
np.sum(sales), np.mean(sales) και np.sum(sales > target). Η NumPy τρέχει τον ίδιο βρόχο, αλλά σε C και για όλα τα στοιχεία μαζί. Οι βρόχοι είναι χρήσιμοι για να καταλαβαίνεις τι γίνεται, αλλά στην ανάλυση δεδομένων τους γράφουμε σπάνια.Η Άσκηση 3 «ανάποδα»: ό,τι έκανες με np.sum(sales > target) και np.sum(sales), τώρα με for, if και δύο συσσωρευτές. Σύγκρινε τους δύο κώδικες στο τέλος.
Στα τέσσερα της εβδομάδας 3 (NameError, TypeError, IndexError, SyntaxError) προστίθενται δύο που θα δεις συχνά με πίνακες, και τα δύο ValueError:
| Μήνυμα | Τι σημαίνει | Διόρθωση |
|---|---|---|
| operands could not be broadcast together with shapes (3,) (2,) | Πράξη ανάμεσα σε πίνακες διαφορετικού μήκους | Έλεγξε τα .shape: λείπει ή περισσεύει τιμή |
| The truth value of an array ... is ambiguous | Χρησιμοποίησες and / or / if πάνω σε ολόκληρο πίνακα | & / | με παρενθέσεις, ή np.logical_and() |
| NameError: name 'np' is not defined | Ξέχασες το import | import numpy as np στην αρχή του script |
| IndexError: index 5 is out of bounds for axis 0 with size 5 | Δείκτης εκτός ορίων (η NumPy σου λέει και τη διάσταση) | 5 στοιχεία = δείκτες 0 έως 4 |
Τρέξε, διάβασε, διόρθωσε ένα σφάλμα τη φορά:
Τρία σφάλματα, τρεις διορθώσεις: ένα NameError, ένα ValueError για shapes και ένα ValueError για το and. Πάτησε «Έλεγξε», διάβασε το μήνυμα, διόρθωσε, ξαναπάτησε.
Δώδεκα ερωτήσεις από όλη την εβδομάδα. Σκέψου πρώτα, μετά απάντησε· αν αμφιβάλλεις, άνοιξε το παράθυρο κώδικα στο τέλος και δοκίμασέ το.