Smart-World Surf

יחידה 7: מבוא לניתוח נתונים עם NumPy

הכרות עם ספריית NumPy לעבודה יעילה עם מערכים מספריים.

ברוכים הבאים ליחידת הלימוד "מבוא לניתוח נתונים עם NumPy", חלק מקורס 20606 "תכנות וניתוח נתונים בשפת פייתון". יחידה זו תציג בפניכם את ספריית NumPy, אבן יסוד בעולם ניתוח הנתונים המדעי בפייתון. נלמד כיצד NumPy מאפשרת עבודה יעילה ומהירה עם מערכים מספריים רב-ממדיים, שהם הבסיס למרבית פעולות ניתוח הנתונים והלמידה העמוקה. הבנה מעמיקה של NumPy חיונית להצלחה בקורס ובתחום בכלל, והיא מהווה בסיס איתן ליחידות מתקדמות יותר.

מבוא ל-NumPy: למה ואיך?

NumPy (Numerical Python) היא ספרייה קריטית בפייתון המספקת אובייקט מערך רב-ממדי (ndarray) ותמיכה בפונקציות מתמטיות מתקדמות לביצוע פעולות על מערכים אלו. היא תוכננה לביצועים גבוהים, במיוחד עבור חישובים מספריים בקנה מידה גדול, והיא מהווה את הבסיס לספריות רבות אחרות בתחום המדע והנתונים, כמו Pandas, SciPy ו-Scikit-learn.

ndarray: אובייקט המערך המרכזי של NumPy, המייצג טבלה (או מטריצה) של אלמנטים מאותו סוג, לרוב מספרים, המאוחסנים באופן רציף בזיכרון.

הצורך ב-NumPy

למרות שרשימות (lists) בפייתון יכולות לאחסן נתונים מספריים, הן אינן מותאמות לביצועים גבוהים של פעולות מתמטיות על קבוצות גדולות של מספרים. NumPy פותרת זאת על ידי:

  • אחסון יעיל בזיכרון: אלמנטים מאותו סוג מאוחסנים ברצף.
  • פעולות וקטוריות: ביצוע פעולות על כל המערך ללא צורך בלולאות מפורשות בפייתון (שאיטיות יותר).
  • מימוש בשפות מהירות: הליבה של NumPy כתובה בשפות כמו C ו-Fortran, מה שמקנה לה יתרון ביצועים משמעותי.

רשימות פייתון (list)

אוסף גמיש של אובייקטים מטיפוסים שונים. איטיות לחישובים מספריים גדולים, צורכות יותר זיכרון.

מערכי NumPy (ndarray)

אוסף הומוגני של אלמנטים מאותו טיפוס. מהירים ויעילים לחישובים מספריים, צורכים פחות זיכרון.

יצירת מערכים ותכונותיהם

יצירת מערכים היא הצעד הראשון בעבודה עם NumPy. ישנן מספר דרכים ליצור מערכים, וחשוב להכיר את תכונותיהם הבסיסיות.

דרכים ליצירת מערכים

  • מתוך רשימת פייתון: np.array([1, 2, 3])
  • מערכים מאופסים/אחדות: np.zeros((2, 3)), np.ones((4,))
  • מערכים עם ערכים קבועים: np.full((2, 2), 7)
  • טווחים מספריים: np.arange(0, 10, 2) (כמו range), np.linspace(0, 1, 5) (טווח עם מספר צעדים קבוע)
  • מערכים אקראיים: np.random.rand(2, 2), np.random.randint(0, 10, size=(3, 3))

תכונות מערך בסיסיות

לכל אובייקט ndarray יש מספר תכונות חשובות:

  • .shape: טופל המייצג את מימדי המערך (לדוגמה: (3, 4) למטריצה 3x4).
  • .ndim: מספר המימדים של המערך (לדוגמה: 2 למטריצה, 1 לווקטור).
  • .size: המספר הכולל של אלמנטים במערך.
  • .dtype: סוג הנתונים של האלמנטים במערך (לדוגמה: int64, float32).

אינדוקס, חיתוך ופעולות על מערכים

היכולת לגשת לאלמנטים ספציפיים במערך, לחתוך חלקים ממנו ולבצע עליו פעולות היא קריטית.

אינדוקס וחיתוך (Indexing & Slicing)

בדומה לרשימות פייתון, ניתן לגשת לאלמנטים באמצעות אינדקסים. במערכים רב-ממדיים, משתמשים בפסיקים להפרדה בין האינדקסים של כל מימד:

  • גישה לאלמנט בודד: arr[0, 1]
  • חיתוך מימד אחד: arr[0, :] (כל העמודות בשורה הראשונה), arr[:, 1] (כל השורות בעמודה השנייה)
  • חיתוך טווח: arr[0:2, 1:3]
  • אינדוקס בוליאני: arr[arr > 5] (מחזיר מערך חד-ממדי של כל האלמנטים הגדולים מ-5).
Broadcasting (שידור): נושא קריטי ובחינתי! זוהי היכולת של NumPy לבצע פעולות על מערכים בעלי צורות שונות. הכללים קובעים כיצד NumPy "ממתיחה" מערכים קטנים יותר כדי להתאים אותם למערכים גדולים יותר במהלך פעולות אריתמטיות. הבנה מעמיקה של כללי השידור חיונית למניעת שגיאות ולכתיבת קוד יעיל.

פעולות על מערכים (Universal Functions - ufuncs)

NumPy מספקת מגוון רחב של פונקציות אוניברסליות (ufuncs) המבצעות פעולות אלמנט-אלמנט על מערכים. אלו מהירות בהרבה מלולאות פייתון:

  • פעולות אריתמטיות: +, -, *, /, ** (חזקה).
  • פונקציות מתמטיות: np.sqrt(), np.exp(), np.log(), np.sin().
  • פונקציות אגרגציה: np.sum(), np.mean(), np.max(), np.min(), np.std(). ניתן לבצע אגרגציה לאורך ציר ספציפי (לדוגמה: arr.sum(axis=0) לסכום עמודות).

שיקולים חשובים וטעויות נפוצות

בעבודה עם NumPy, ישנם מספר נושאים הדורשים תשומת לב מיוחדת כדי למנוע טעויות ולשפר את ביצועי הקוד.

עותק מול תצוגה (Copy vs. View)

כאשר חותכים מערך, NumPy לעיתים קרובות יוצרת "תצוגה" (view) של המערך המקורי במקום "עותק" (copy). שינוי בתצוגה ישפיע גם על המערך המקורי. כדי להבטיח עותק עצמאי, יש להשתמש בשיטה .copy():

  • תצוגה: sub_array = arr[0:2, :] (שינוי ב-sub_array ישנה את arr).
  • עותק: sub_array_copy = arr[0:2, :].copy() (שינוי ב-sub_array_copy לא ישנה את arr).

שינוי צורה (Reshaping)

ניתן לשנות את צורתו של מערך מבלי לשנות את הנתונים עצמם, כל עוד מספר האלמנטים נשאר זהה. השיטה .reshape() שימושית לכך:

  • arr.reshape((new_rows, new_cols))
  • ניתן להשתמש ב--1 כארגומנט אחד כדי ש-NumPy תחשב אוטומטית את המימד המתאים (לדוגמה: arr.reshape((2, -1))).

שאלות לדיון

  • מדוע ספריית NumPy נחשבת לחיונית לניתוח נתונים בפייתון, ומהם היתרונות המרכזיים שלה על פני רשימות פייתון רגילות עבור נתונים מספריים?
  • הסבירו את הרעיון של "Broadcasting" ב-NumPy. תנו דוגמה לפעולה שבה Broadcasting נכנס לפעולה והסבירו כיצד NumPy מטפלת בה.
  • מה ההבדל בין "תצוגה" (view) ל"עותק" (copy) של מערך ב-NumPy? מתי חשוב להשתמש במפורש ב-.copy() ומדוע?
  • תארו מצב שבו תשתמשו באינדוקס בוליאני (Boolean Indexing) כדי לסנן נתונים ממערך NumPy. ספקו דוגמת קוד קצרה.

נקודות לתשובת מודל

  • יתרונות NumPy: יעילות בזיכרון, מהירות חישובים בזכות מימוש ב-C/Fortran, פעולות וקטוריות (ufuncs) המונעות לולאות פייתון איטיות, אובייקט ndarray הומוגני.
  • Broadcasting: מנגנון המאפשר לבצע פעולות אריתמטיות על מערכים בעלי צורות שונות. NumPy "ממתיחה" מערכים קטנים יותר כדי שיתאימו לגדולים יותר. דוגמה: חיבור וקטור לשורות של מטריצה (matrix + vector). הכללים כוללים התאמה מהמימד האחרון קדימה, ומימד בגודל 1 יכול להיות "מתוח".
  • Copy vs. View: "תצוגה" היא הפניה לאותם נתונים בזיכרון כמו המערך המקורי; שינוי בתצוגה משנה את המקור. "עותק" הוא שכפול עצמאי של הנתונים. חשוב להשתמש ב-.copy() כאשר רוצים לוודא ששינויים בחלק מהמערך לא ישפיעו על המערך המקורי, לדוגמה, בעת חיתוך.
  • אינדוקס בוליאני: שיטה לסינון אלמנטים ממערך על בסיס תנאי לוגי. יוצרים מערך בוליאני באותה צורה כמו המערך המקורי, כאשר True מציין אלמנטים שיש לכלול. דוגמה: arr[arr > 10] יחזיר את כל האלמנטים ב-arr שגדולים מ-10.
מצאתם טעות או שחסר משהו?
→ הקודמת
מודולים וחבילות
הבאה ←
ניהול ועיבוד נתונים עם Pandas