שימו לב: על מנת להריץ את התאים ב-Live Code, יש לייבא תחילה את ספרית pandas ע”י הרצת השורת הראשונה בתא למטה.
בנוסף, נגביל את מספר השורות והעמודות שתופענה בהדפסת הטבלאות ע”י שורות הקוד השניה והשלישית:
import pandas as pd
pd.options.display.max_rows=5
pd.options.display.max_columns=5
גישה בסיסית לטבלה#
עכשיו כשאנחנו יודעים ליצור טבלאות, נתחיל ללמוד כיצד עובדים איתן.
נתחיל מטעינת טבלת הציונים שלנו מהקובץ files/StudentsGrades.csv לתוך df:
inputFileName = "files/StudentsGrades.csv"
df = pd.read_csv(inputFileName)
display(df)
| Name | Programming | ... | Planet Survival | Art | |
|---|---|---|---|---|---|
| 0 | Yael | 50 | ... | 65 | 91 |
| 1 | Nadav | 61 | ... | 52 | 88 |
| ... | ... | ... | ... | ... | ... |
| 11 | Tom | 98 | ... | 92 | 80 |
| 12 | Adi | 76 | ... | 84 | 70 |
13 rows × 8 columns
בדיקת נתונים בסיסיים על הטבלה#
כדי להכיר את הטבלה יותר טוב, נרצה לחלץ ממנה מספר נתונים בסיסיים.
כדי לקבל את מספר השורות בטבלה, נוכל להשתמש בפונקציה שכבר ראינו - len:
print(len(df))
13
מה לגבי מספר העמודות?
בדומה לarray בnumpy, גם בDataFrame בpandas ישנו שדה מיוחד בשם shape, המייצג את מימדי הטבלה כtuple:
print(df.shape)
(13, 8)
כפי שהזכרנו ביחידה הקודמת, כל עמודה יכולה להכיל ערכים מטיפוס שונה. כדי לקבל את הטיפוס של העמודות ניתן להשתמש בשדה dtypes:
print(df.dtypes)
Name object
Programming int64
...
Planet Survival int64
Art int64
Length: 8, dtype: object
שימו לב
עמודות מחרוזת (כמו Name בדוגמא לעיל) מיוצגות בpandas ע”י הטיפוס object
גישה לערכים בטבלאות וסדרות: [], [,]iloc ו-[,]loc#
טקסט המופיע למטה בסגול מציין קטעים המופיעים בסרטון
ניתן להיעזר בו כדי לחזור על התכנים או לעיין בהם שוב.
בpandas קיימות מספר דרכים לגשת לנתונים מטבלה. השיטה הפשוטה ביותר היא df[x], שמחזירה עמודה לפי השם שלה. אם נפעיל את [] על סדרה (Series), לדוגמא, s[x], נקבל ערך שנמצא בתא בשם x.
בנוסף, קיימות שתי מתודות מאוד שימושיות: df.loc[x,y] שמבוססת על שמות השורות (x) ועמודות (y), ו־df.iloc[x,y] שמבוססת על המיקומי של השורות והעמודות (x ו-y) בהתאמה.
באמצעות מתודות אלו, ניתן לבצע חיתוך על השורות והעמודות יחדיו בתוך הסוגריים המרובעים.
df[x]
s[x]
df.loc[x,y]
df.iloc[x,y]
בכל אחת מהאופציות הללו, x יכול לייצג עבור טבלה:
שורה בודדת
Slicing של שמות/מיקומי שורות
רשימה של שמות/מיקומי שורות.
באופן דומה ניתן לגשת לעמודה בודדת או מספר עמודות באמצעות y.
חשוב להבחין בין שלושת הדרכים הללו, משום שכל אחת מהן מתנהגת אחרת.
כאשר ניגשים לערכים בטבלה, סוג האובייקט שניגשים אליו תלוי בכמות השורות והעמודות שנבחרו:
גישה לתא יחיד מחזירה ערך בודד בהתאם לטיפוס הנתונים של העמודה.
גישה לעמודה אחת או שורה אחת מחזירה אובייקט מסוג
Series, שהוא וקטור חד-ממדי.גישה למספר עמודות ומספר שורות, התוצאה היא
DataFrame, כלומר טבלה דו-ממדית.
שימוש בiloc[x,y]#
שימוש בiloc[x,y] בטבלה#
באמצעות שימוש בiloc מתאפשרת גישה לערכים, שורות ועמודות לפי מיקומים מספריים (בדומה לגישה לערכים ברשימות, מערכים ומטריצות).
לדוגמא, ניתן לגשת לערך בודד באמצעות ציון השורה והעמודה של הערך. לדוגמא, כך נחזיר את הערך הנמצא בשורה השניה והעמודה השניה:
print(df.iloc[1, 1])
61
על מנת לגשת לשורה שלמה, נפרט רק את האינדקס הראשון. לדוגמא, הקוד הבא מחלץ את השורה הראשונה (אינדקס 0):
s = df.iloc[0]
print(s)
Name Yael
Programming 50
...
Planet Survival 65
Art 91
Name: 0, Length: 8, dtype: object
ניתן לראות כי במקרה הזה מכיוון שחילצנו שורה, הערך שחזר הוא מטיפוס series
print(type(s))
<class 'pandas.core.series.Series'>
כאשר רוצים להחזיר שורה בודדת, בברירת המחדל נבחרים ערכי כל העמודות באותה השורה.
ואם נרצה לבחור עמודה? נוכל לשים את האינדקס של העמודה במיקום השני בסוגריים המרובעים (כלומר, לאחר הפסיק).
אך בניגוד להחזר שורה, אין ערך ברירת מחדל לערכי השורות שחוזרות עבור העמודה. על מנת להחזיר את כל ערכי השורות של העמודה, נוכל להשתמש ב: ללא פירוט נוסף. כפי שראינו בslicing, : משתמשים לציון כל הטווח, כלומר, במקרה שלנו, ערכי העמודה בכל השורות.
print(df.iloc[:,0])
0 Yael
1 Nadav
...
11 Tom
12 Adi
Name: Name, Length: 13, dtype: object
ניתן גם לבחור תת טבלה לפי טווחים של שורות ושל עמודות יחד.
display(df.iloc[0:3,0:3])
| Name | Programming | Marine Biology | |
|---|---|---|---|
| 0 | Yael | 50 | 56 |
| 1 | Nadav | 61 | 77 |
| 2 | Michal | 81 | 72 |
שימוש בiloc[x,y] בסדרה#
בדומה לטבלה, גם מסדרה ניתן לחלץ ערכים.
בדוגמא למטה, נחלץ תחילה שורה הרביעית בטבלה:
df_row=df.iloc[3]
כעת נוכל להשתמש בiloc (שוב) כדי לחלץ ערך מהסדרה:
print(df_row.iloc[0])
Shoshana
כלומר, כאן חילצנו את הערך הראשון של הסדרה, שהוא למעשה ערך העמודה הראשונה בשורה הרביעית.
כפי שהזכרנו קודם, הטיפוס של שורה הוא series, כלומר, סדרת ערכים חד מימדית. לכן נוכל לבחור רק לפי מימד אחד של אינדקסים (כלומר, x ללא y).
אם ננסה לבחור גם לפי y נקבל שגיאה:
print(df_row.iloc[:,0])
---------------------------------------------------------------------------
IndexingError Traceback (most recent call last)
Cell In[15], line 1
----> 1 print(df_row.iloc[:,0])
File /opt/hostedtoolcache/Python/3.11.14/x64/lib/python3.11/site-packages/pandas/core/indexing.py:1185, in _LocationIndexer.__getitem__(self, key)
1183 if self._is_scalar_access(key):
1184 return self.obj._get_value(*key, takeable=self._takeable)
-> 1185 return self._getitem_tuple(key)
1186 else:
1187 # we by definition only have the 0th axis
1188 axis = self.axis or 0
File /opt/hostedtoolcache/Python/3.11.14/x64/lib/python3.11/site-packages/pandas/core/indexing.py:1691, in _iLocIndexer._getitem_tuple(self, tup)
1690 def _getitem_tuple(self, tup: tuple):
-> 1691 tup = self._validate_tuple_indexer(tup)
1692 with suppress(IndexingError):
1693 return self._getitem_lowerdim(tup)
File /opt/hostedtoolcache/Python/3.11.14/x64/lib/python3.11/site-packages/pandas/core/indexing.py:963, in _LocationIndexer._validate_tuple_indexer(self, key)
958 @final
959 def _validate_tuple_indexer(self, key: tuple) -> tuple:
960 """
961 Check the key for valid keys across my indexer.
962 """
--> 963 key = self._validate_key_length(key)
964 key = self._expand_ellipsis(key)
965 for i, k in enumerate(key):
File /opt/hostedtoolcache/Python/3.11.14/x64/lib/python3.11/site-packages/pandas/core/indexing.py:1002, in _LocationIndexer._validate_key_length(self, key)
1000 raise IndexingError(_one_ellipsis_message)
1001 return self._validate_key_length(key)
-> 1002 raise IndexingError("Too many indexers")
1003 return key
IndexingError: Too many indexers
שימוש בloc[x,y]#
הגישה באמצעות loc מאפשרת לנו לבחור שורות ועמודות לפי שמות, ולא לפי מיקומים מספריים. זוהי אחת מהדרכים הברורות והנוחות ביותר לגשת למידע בDataFrame.
הגישה לערכי שורות ועמודות בloc זהה בתחביר לגישה עםiloc, אך כעת נפרט את שמות השורות ושמות והעמודות ולא את האינדקסים.
לדוגמא, ניגש לעמודת הציונים במקצוע אמנות באופן הבא:
display(df.loc[:,'Art'])
כעת ניגש לשורה בטבלה לפי שמה.
כפי שציינו מוקדם יותר ביחידה, שמות השורות הן בברירת מחדל סדרת מספרים המתחילה מ0. לכן, גישה לשורות לפי loc וiloc עשויה להראות בהתחלה מעט דומה.
לדוגמא, בשתי שורות הקוד שלהלן אנו מחזירים פעמיים את השורה הראשונה תוך שימוש דומה בloc וiloc
display(df.loc[0])
Name Yael
Programming 50
...
Planet Survival 65
Art 91
Name: 0, Length: 8, dtype: object
display(df.iloc[0])
Name Yael
Programming 50
...
Planet Survival 65
Art 91
Name: 0, Length: 8, dtype: object
ניתן גם לתת לשורות שמות בעלי משמעות, ולחלץ שורות לפי שמות אלו.
כדי להדגים זאת, נשתמש במתודה set_index כדי לשנות את שמות שורות בטבלה לערכים המופעים בעמודה Name:
df = df.set_index("Name")
display(df)
| Programming | Marine Biology | ... | Planet Survival | Art | |
|---|---|---|---|---|---|
| Name | |||||
| Yael | 50 | 56 | ... | 65 | 91 |
| Nadav | 61 | 77 | ... | 52 | 88 |
| ... | ... | ... | ... | ... | ... |
| Tom | 98 | 76 | ... | 92 | 80 |
| Adi | 76 | 87 | ... | 84 | 70 |
13 rows × 7 columns
שימו לב
בברירת המחדל, המתודה
set_indexמורידה את העמודה שהיא הופכת לאינדקסיש להמנע מהגדרת ערכי אינדקסים המכילים כפילויות, מכיוון שזה עלול לגרור שגיאות בשימושים רבים ב
pandas
כעת נוכל לחלץ באמצעות loc את השורה לפי שמות הסטודנטים:
print(df.loc['Adi'])
Programming 76
Marine Biology 87
..
Planet Survival 84
Art 70
Name: Adi, Length: 7, dtype: int64
כעת נחלץ את הציון של עדי נדב באמנות:
print(df.loc[['Adi','Nadav'], 'Art'])
Name
Adi 70
Nadav 88
Name: Art, dtype: int64
הערה
כאשר מעבירים שמות שורות (או עמודות) ברשימה לloc סדר השורות (או העמודות) שיוחזר יהיה תואם לסדר של השמות ברשימה.
התנהגות דומה תהיה גם עבור iloc עם רשימת אינדקסים
השוואה בין iloc לloc#
נטען מחדש את הטבלה המקורית:
inputFileName = "files/StudentsGrades.csv"
df = pd.read_csv(inputFileName)
display(df)
נראה כעת שלוש דרכים לחלץ את השורה הראשונה, השלישית והחמישית מתוך df:
display(df.iloc[[0,2,4]])
| Name | Programming | Marine Biology | Stellar Cartography | Math | History | Planet Survival | Art | |
|---|---|---|---|---|---|---|---|---|
| 0 | Yael | 50 | 56 | 70 | 60 | 87 | 65 | 91 |
| 2 | Michal | 81 | 72 | 76 | 94 | 67 | 81 | 78 |
| 4 | Danielle | 36 | 74 | 82 | 40 | 78 | 86 | 65 |
display(df.iloc[0:5:2])
| Name | Programming | Marine Biology | Stellar Cartography | Math | History | Planet Survival | Art | |
|---|---|---|---|---|---|---|---|---|
| 0 | Yael | 50 | 56 | 70 | 60 | 87 | 65 | 91 |
| 2 | Michal | 81 | 72 | 76 | 94 | 67 | 81 | 78 |
| 4 | Danielle | 36 | 74 | 82 | 40 | 78 | 86 | 65 |
display(df.loc[0:4:2])
| Name | Programming | Marine Biology | Stellar Cartography | Math | History | Planet Survival | Art | |
|---|---|---|---|---|---|---|---|---|
| 0 | Yael | 50 | 56 | 70 | 60 | 87 | 65 | 91 |
| 2 | Michal | 81 | 72 | 76 | 94 | 67 | 81 | 78 |
| 4 | Danielle | 36 | 74 | 82 | 40 | 78 | 86 | 65 |
שימו לב
בניגוד לסדרות מספריות כפי שראינו עד כה בקורס, Slicing לפי שמות (ב[] ו-loc[]) רץ מהשם בראשון *כולל עד השם האחרון כולל, לפי סדר הופעת השורות/העמודות.
שימוש בSlicing בiloc[] מתנהג כפי שראינו עד כה בSlicing: כלומר, רץ מהמספר הראשון כולל עד האחרון לא כולל
בגלל שבדוגמא האחרונה אנו משתמשים בloc הגדרנו את הטווח עד 4 ולא 5.
אם היינו מנסים להפעיל אותו slicing על iloc, לא היינו מקבלים את הערך החמישי:
display(df.iloc[0:4:2])
| Name | Programming | Marine Biology | Stellar Cartography | Math | History | Planet Survival | Art | |
|---|---|---|---|---|---|---|---|---|
| 0 | Yael | 50 | 56 | 70 | 60 | 87 | 65 | 91 |
| 2 | Michal | 81 | 72 | 76 | 94 | 67 | 81 | 78 |
תרגול#
חלצו מהטבלה
dfאת ארבע השורות האחרונות בכל אחת משלוש השיטות שהדגמנו למעלה.
רמז: השתמשו באינדקסים שליליים.
# Write your code here
בשורה להלן בוצע ניסיון לחלץ את השורה האחרונה מהטבלה
print(df.loc[-1])
מדוע התקבלה שגיאה?
לחצו כאן כדי לצפות בתשובה
המתודה loc ניגשת לשורות לפי השמות שלהן. על מנת לגשת לפי מיקום (-1), יש להשתמש בiloc
שימוש ב[]#
שימוש ב[] בטבלה#
כאשר משתמשים בסוגריים מרובעים [] עם אובייקט מסוג DataFrame, ברירת המחדל היא גישה לעמודה לפי שמה.
כמו בloc, גם כאן ניתן להעביר שם בודד, רשימת שמות, או טווח של שמות.
לדוגמא, השורה הבאה תחזיר את הציונים באמנות:
display(df["Art"])
Name
Yael 91
Nadav 88
..
Tom 80
Adi 70
Name: Art, Length: 13, dtype: int64
והשורה שלהלן תחזיר את הציונים באמנות ובתכנות:
display(df[["Art", "Programming"]])
| Art | Programming | |
|---|---|---|
| Name | ||
| Yael | 91 | 50 |
| Nadav | 88 | 61 |
| ... | ... | ... |
| Tom | 80 | 98 |
| Adi | 70 | 76 |
13 rows × 2 columns
בדומה לloc וiloc, גם ב[] יוחזר טיפוס series עבור שם בודד (עמודה בודדת) וטבלה עבור מספר עמודות.
ואם נעביר ערך שאינו קיים?
בדוגמא הבאה ננסה לגשת לעמודה שאינה קיימת בשם 1, וכפי שאנו רואים, מתקבלת שגיאה:
df[1]
שימוש ב[] בסדרה#
אם נפעיל את [] על סדרה (Series), לדוגמא, s[x], נקבל ערך שנמצא בתא בשם x.
s = df["Art"]
print(type(s))
print(s[0])
<class 'pandas.core.series.Series'>
91
שמות שורות ועמודות בטבלאות וסדרות#
ב-DataFrame שמות השורות ושמות העמודות נשמרים בשדות ייעודיים:
שמות השורות נשמרים בשדה
indexשמות העמודות נשמרים במאפיין
columns
שני השדות הם מסוג המחלקה Index, שניתן לראות בה מחלקה כללית לייצוג שמות.
שמות התאים בתוך Series נקראים גם הם index, ללא קשר אם ה-Series מייצגת מעמודה או משורה.
זכרו כי Series היא חד-מימדית בעוד הקונספט של שורה ועמודה נגזר מכך קיים רק בהקשר של DataFrame - באיך שה-Series ממקום בו (בדומה לשורה או עמודה בודדת במטריצה).
s=df.loc[0]
print(type(s))
print(s.index)
<class 'pandas.core.series.Series'>
Index(['Name', 'Programming', 'Marine Biology', 'Stellar Cartography', 'Math',
'History', 'Planet Survival', 'Art'],
dtype='object')
לסדרה גם יכול להיות שם, השמור בשדה name. אם הסדרה נגזרה משורה/עמודה בטבלה, הערך של nameיהיה שם השורה או העמודה כפי שהופיע במקור בטבלה:
print(s.name)
0