מבוא
ספריית pandas היא python package שמאפשרת עבודה מהירה, גמישה ואינטואיטיבית
עם מבני נתונים רלציונים. יוצרי הספריה התכוונו ליצור ספריה שתהיה ה-ספריה היסודית
עבור data
analysis ב-python. ספריית pandas היא פרוייקט קוד פתוח נפוץ מאוד בשימוש בפרוייקטים של Machine Learning ובפרוייקטים
נוספים רבים. לספריית pandas יש ביצועים מהירים. חלק גדול מקוד ה-low level שלה נכתב ב-Cython (קומפיילר שמאפשר כתיבת הרחבות
ל-python ב-C/C++). אבל כמובן כדי ליצור ספרייה
גנרית יש צורך לפעמים להקריב ביצועים לשם כך. לכן אם הפרוייקט שלכם נצרך לפעולה
מסויימת הרבה פעמים, יתכן שתוכלו לכתוב קוד מיוחד לצרכים שלכם שיהיה מהיר יותר.
pandas במושתת על NumPy לכן כדי להשתמש ב-Pandas צריך לייבא את NumPy ואת pandas:
pandas במושתת על NumPy לכן כדי להשתמש ב-Pandas צריך לייבא את NumPy ואת pandas:
>>> import numpy as np >>> import pandas as pd
מבני נתונים
ל-pandas יש שני מבני
נתונים עיקריים:
1. Series – מבנה
נתונים חד-ממדי
2. DataFrame – מבנה נתונים
דו-ממדי (df בקיצור)
דרך פשוטה לחשוב על מבני הנתונים היא שמבנה נתונים מורכב יותר מחזיק מבני נתונים
פשוטים יותר. למשל DataFrame מכיל Series ו-Series מכיל סקלאר.
כשמשתמשים במערך של NumPy (נקרא ndarray) להחזיק מבנה דו-ממדי או תלת-ממדי, צריך לשים לב תמיד באיזה מימד
נמצאים הנתונים ולהתאים את הפעולות לפי צורת שמירת הנתונים. לעומת זאת ב-Pandas המימדים הם יותר עניין סמנטי
עבור המידע. במקום לדבר על עמודה ראשונה ועמודה שניה מדברים על אינדקס המידע ועל עמודות
המידע. כך הקוד נהיה יותר קריא ודורש פחות השקעת מחשבה על צורת שמירת הנתונים.
לדוגמה:
>>> for col in df.columns: series = df[col]
כל מבני הנתונים ב-Pandas הם value-mutable, ז"א שניתן לשנות ערכים בתוך מבנה נתונים. אבל לא תמיד ניתן לשנות את גודל מבנה הנתונים. למשל, אורך Series לא ניתן לשינוי. לעומת זאת, ניתן להוסיף עמודות ל-df.
עם זאת, רוב הפונקציות יוצרות אובייקטים חדשים ולא משנות את ה-Input שהן קיבלו.
Series
ה-series הוא מבנה חד-ממדי הכולל תוויות (labeled), שיכול להכיל כל סוג מידע (integers, strings, floating point numbers, Python objects וכו'). התוויות של המידע נקראות גם אינדקס.
הדרך הפשוטה ביותר ליצור series היא:
הדרך הפשוטה ביותר ליצור series היא:
>>> s = pd.Series(data, index=index)
כאשר:
- data - הנתונים עצמם. יכול להיות Python dict, או ndarray או מספרים ממש.
- index - תוויות הנתונים. רשימה של התוויות של המידע. וזה דבר שמשתנה לפי סוג המידע.
From ndarray
אם ה-data הוא ndarray, אז האינדקס חייב להיות באותו אורך של ה-data. אם לא שלחנו אינדקס הוא יווצר אוטומטית מאפס ועד לכמות הנתונים פחות אחד.
דוגמה:
>>> s = pd.Series(np.random.randn(5), index=['first','second','third','fourth','fifth']) >>> s first -1.873184 second 1.041916 third 1.027184 fourth -0.691705 fifth 1.291348 dtype: float64 >>> s.index Index(['first', 'second', 'third', 'fourth', 'fifth'], dtype='object') >>> r = pd.Series(np.random.randn(5)) >>> r 0 -1.512113 1 0.746104 2 -0.542947 3 0.356579 4 -0.803947 dtype: float64
הערה: pandas מאפשר גם אינדקסים לא ייחודיים (שני אינדקסים זהים). אם מנסים לבצע על מבנה שמכיל אינדקסים זהים פעולה שלא תומכת באינדקסים זהים, נקבל שגיאה.
From dict
ניתן ליצור Series מ-dict.
לדוגמה:
לדוגמה:
>>> d = {'c':1,'a':2,'b':3} >>> pd.Series(d) c 1 a 2 b 3 dtype: int64
הערה:
עבור python>=3.6 עם pandas>=0.23: כאשר ה-data הוא dict ולא מספקים אינדקס, האינדקס ב-series יהיה לפי הסדר שהופיע ב-dict
עבור python<3.6 או pandas<0.23: האינדקס ימויין
בסדר לקסיקלי (לפי סדר האותיות והמספרים) לפי ה-keys שב-dict. בדוגמה לעיל ה-series היה בסדר [‘a’,’b’,’c’] במקום [‘c’,’a’,’b’].
כדי לבדוק את גרסת ה-python נכתוב בשורת הפקודה:
python --version
כדי לבדוק את גרסת ה-pandas נכתוב:
pd.__version__
אם יחד עם ה-dict שולחים גם אינדקס מקבלים Series שמורכב מהערכים לפי האינדקסים המבוקשים.
>>> pd.Series(d,index=['a','b','a','d']) a 2.0 b 3.0 a 2.0 d NaN dtype: float64
אם יש אינדקס שלא קיים pandas מכניס לו ערך של NaN שזה קיצור של Not a Number. זו הדרך של Pandas להשלמת ערכים חסרים.
From scalar
ניתן ליצור Series ממספר פשוט. אותו מספר יהיה הערך לכל האינדקסים.
לדוגמה:
לדוגמה:
>>> pd.Series(3 ,index=['a','b','c']) a 3 b 3 c 3 dtype: int64
Series לעומת ndarray
Series פועל בצורה דומה ל-ndarray של NumPy. וניתן לשלוח אותו כפרמטר עבור רוב פונקציות NumPy. צריך לשים לב שחיתוך של Series יחתוך גם את האינקדסים.
להלן כמה דוגמאות:
בדומה ל-ndarray גם ל-Series יש dtype:
להלן כמה דוגמאות:
>>> s = pd.Series(np.random.randn(5), index=['first','second','third','fourth','fifth']) >>> s first -0.613318 second 0.531901 third 0.750628 fourth -2.339552 fifth 0.054086 dtype: float64 >>> s[1] 0.5319012043677321 >>> s[:2] first -0.613318 second 0.531901 dtype: float64 >>> s[s > s.median()] second 0.531901 third 0.750628 dtype: float64 >>> s[s < s.mean()] first -0.613318 fourth -2.339552 dtype: float64 >>> s[[0, 4, 1]] first -0.613318 fifth 0.054086 second 0.531901 dtype: float64 >>> np.exp(s) first 0.541551 second 1.702165 third 2.118329 fourth 0.096371 fifth 1.055576 dtype: float64
בדומה ל-ndarray גם ל-Series יש dtype:
>>> s.dtype dtype('float64')
בד"כ ה-dtype הוא מאחד הסוגים של NumPy. בנוסף, ב-pandas הוסיפו עוד כמה סוגים של נתונים. במקרים האלו ה-dtype יהיה ExtensionDtype.
אם יש צורך במערך עצמו שה-Series מחזיק ניתן לגשת אליו דרך Series.array:
>>> s.array <PandasArray> [ -0.6133182061989823, 0.5319012043677321, 0.7506275056129353, -2.3395522211220814, 0.054086401543235095] Length: 5, dtype: float64
זה יכול להיות שימושי כשצריך לעשות פעולות ללא האינדקסים.
ה-Series.array יהיה תמיד מסוג ExtensionArray. שזה בעצם מעטפת סביב מערך אמיתי כמו ndarray.
אם אנחנו רוצים להמיר Series ל-ndarray ניתן להשתמש ב-()Series.to_numpy:
ה-Series.array יהיה תמיד מסוג ExtensionArray. שזה בעצם מעטפת סביב מערך אמיתי כמו ndarray.
אם אנחנו רוצים להמיר Series ל-ndarray ניתן להשתמש ב-()Series.to_numpy:
>>> s.to_numpy() array([-0.61331821, 0.5319012 , 0.75062751, -2.33955222, 0.0540864 ])
שימוש Series בדומה ל-dictionary
ה-Series הוא כמו dict בגודל קבוע וניתן לשמור בו נתונים ולקבל ממנו נתונים ע"י שימוש באינדקס שלו שמשמש כ-label:
>>> s = pd.Series(pd.np.random.randn(5), index=['a','b','c','d','e']) >>> s a -2.690282 b -1.830599 c -0.648347 d -0.556113 e 0.809609 dtype: float64 >>> s['b'] -1.8305993446632571 >>> s['b']=17 >>> s a -2.690282 b 17.000000 c -0.648347 d -0.556113 e 0.809609 dtype: float64 >>> 'c' in s True >>> 'g' in s False
אם מנסים לקחת אינדקס שלא קיים נזרק exception:
>>> s['g'] KeyError: 'g'
לעומת זאת אם משתמשים ב-get עבור אינדקס שלא קיים מקבלים None ואפשר גם להגדיר ערך שיוחזר במקרה שאינדקס לא קיים:
>>> a = s.get('g') >>> a is None True >>> s.get('g', 0) 0
פעולות וקטוריות
בדומה ל-NumPy נדיר שיהיה צורך לעשות פעולה על מערך בעזרת לולאה. ברוב המקרים ניתן לעשות פעולות וקטוריות ובכך להימנע מלולאות ולקבל תוכנה מהירה יותר.
לדוגמה:
לדוגמה:
>>> s+s a -5.380563 b 34.000000 c -1.296693 d -1.112225 e 1.619218 dtype: float64 >>> s * 3 a -8.070845 b 51.000000 c -1.945040 d -1.668338 e 2.428827 dtype: float64 >>> np.exp(s) a 6.786182e-02 b 2.415495e+07 c 5.229096e-01 d 5.734338e-01 e 2.247029e+00 dtype: float64
פעולות בין Series עם תויות שונות - label alignment
כאשר מבצעים פעולות בין שני Series, הפעולות יתבצעו בין הערכים בעלי אותו אינדקס. דבר כזה נקרא label alignment. אם אינדקס מסוים קיים ב-Series אחד אבל לא בשני התוצאה תהיה NaN.
לדוגמה:
>>> s = pd.Series(np.arange(5), index=['a','b','c','d','e']) >>> r = pd.Series(np.arange(5), index=['b','c','d','e','f']) >>> s a 0 b 1 c 2 d 3 e 4 dtype: int32 >>> r b 0 c 1 d 2 e 3 f 4 dtype: int32 >>> s + r a NaN b 1.0 c 3.0 d 5.0 e 7.0 f NaN dtype: float64
אם רוצים להיפטר מכל האינדקסים שמכילים NaN ניתן להשתמש בפונקציה dropna:
>>> (s + r).dropna() b 1.0 c 3.0 d 5.0 e 7.0
נתינת שם ל-Series
ניתן לתת שם ל-Series ע"י המשתנה name שיש לכל אובייקט מסוג Series.
>>> s = pd.Series(np.arange(3), index=['a','b','c'], name = 'mySeries') >>> s.name 'mySeries'
כשיוצרים Series חדש מאחד קיים ניתן ליצור אותו עם שם חדש:
>>> s1 = s.rename('yourSeries') >>> s1 a 0 b 1 c 2 Name: yourSeries, dtype: int32
עכשיו s ו-s1 הם שני Series שונים. ושינוי של אחד לא ישפיע על השני.
עד כאן להפעם.
אם אהבתם, תכתבו משהו למטה...
אין תגובות:
הוסף רשומת תגובה