שימו לב: על מנת להריץ את התאים ב-Live Code, יש לייבא תחילה את ספרית pandas ע”י הרצת השורת הראשונה בתא למטה.
בנוסף, נגביל את מספר השורות והעמודות שתופענה בהדפסת הטבלאות ע”י שורות הקוד השניה והשלישית:
import pandas as pd
pd.options.display.max_rows=5
pd.options.display.max_columns=5
עריכה בסיסית של טבלאות וסדרות#
בשלב זה כבר למדנו כיצד ליצור טבלאות (DataFrame) וסדרות (Series), ולגשת לערכים שבתוכן. כעת נתקדם צעד נוסף — נראה כיצד לערוך ולעבד את הנתונים עצמם.
בפרק זה נלמד לבצע פעולות בסיסיות אך חיוניות: חיבור וחיסור בין עמודות, חישוב ממוצעים, הוספה והסרה של עמודות מטבלה ועוד.
יכולות אלה מהוות את הבסיס לעבודה אמיתית עם נתונים — כאשר לעיתים קרובות נרצה לגזור מידע חדש מהקיים, לעדכן את הנתונים בהתאם לצורך, או לצמצם את הטבלה רק לעמודות הרלוונטיות לנו.
הפעולות להלן יודגמו טבלת הציונים "files/StudentsGrades.csv":
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
פעולות אריתמטיות בין טבלאות וסדרות#
ניתן לבצע מגוון פעולות אריתמטיות בין טבלאות וסדרות.
הפעולות מבוצעות איבר-איבר (element-wise), כלומר, עבור כל זוג ערכים נמצאים בתא בעל שם תואם ב2 העמודות.
נראה כאן כמה דוגמאות:
בדוגמא הזאת ביצענו חיסור בין עמודות:
print(df['Math'] - df['Art'])
0 -31
1 -13
..
11 20
12 20
Length: 13, dtype: int64
התוצאה של פעולת החיסור היא סדרה חדשה המכילה את ערכי ההפרש בין העמודות.
ניתן לבצע גם פעולה אריתמטית בין סדרה לסקאלר. לדוגמא, חישוב ממוצע בין שתי עמודות:
print((df['Math'] + df['Art'])/2)
0 75.5
1 81.5
...
11 90.0
12 80.0
Length: 13, dtype: float64
ומה אם נרצה לחשב ממוצע כל טבלה בעלת 10 עמודות?
בשביל פעולות כאלו יצרו מתודות יעודיות. לדוגמא, על מנת לחשב ממוצע נוכל להשתמש במתודת mean:
display(df.iloc[:,1:].mean(axis=1))
0 68.428571
1 70.142857
...
11 91.714286
12 75.571429
Length: 13, dtype: float64
וכדי לחשב סכום, נשתמש במתודת sum:
display(df.iloc[:,1:].sum(axis=1))
0 479
1 491
...
11 642
12 529
Length: 13, dtype: int64
הערה
הקלט axis=1 אומר שיש לחשב עמודת ממוצעים. במילים אחרות, לחשב ממוצע על כל שורה בנפרד שמסתכם לכדי עמודה בודדת
חשבו
מדוע השתמשנו כאן בiloc[:,1:]?
הסרת שורות ועמודות#
על מנת להסיר שורות או עמודות, נשתמש במתודה drop של DataFrame**, המחזירה טבלה חדשה ללא השורות/עמודות בעלות השמות שצוינו. ניתן להעביר שם בודד או מספר שמות של שורות/עמודות אותם אנו רוצים להסיר.
הפרמטר axis קובע היכן תתבצע ההסרה - בשורות (axis=0) או בעמודות (axis=1).
דוגמא להסרת העמודה Name:
display(df.drop('Name', axis=1))
| Programming | Marine Biology | ... | Planet Survival | Art | |
|---|---|---|---|---|---|
| 0 | 50 | 56 | ... | 65 | 91 |
| 1 | 61 | 77 | ... | 52 | 88 |
| ... | ... | ... | ... | ... | ... |
| 11 | 98 | 76 | ... | 92 | 80 |
| 12 | 76 | 87 | ... | 84 | 70 |
13 rows × 7 columns
דוגמא להסרת השורה הראשונה והאחרונה.
display(df.drop([0,12]))
| Name | Programming | ... | Planet Survival | Art | |
|---|---|---|---|---|---|
| 1 | Nadav | 61 | ... | 52 | 88 |
| 2 | Michal | 81 | ... | 81 | 78 |
| ... | ... | ... | ... | ... | ... |
| 10 | Yaniv | 100 | ... | 88 | 90 |
| 11 | Tom | 98 | ... | 92 | 80 |
11 rows × 8 columns
שימו לב
אם השם לא מופיע בציר שצוין, drop תקפיץ שגיאה
הערה
בברירת המחדל הערך של axis הוא תמיד 0 - כלומר, הפעולה תתייחס לשורות
ואם נרצה להסיר את השורות או העמודות מהטבלה המקורית?
במקרה זה, נוכל להשתמש בפרמטר in_place=True:
df.drop(0, inplace=True)
display(df)
| Name | Programming | ... | Planet Survival | Art | |
|---|---|---|---|---|---|
| 1 | Nadav | 61 | ... | 52 | 88 |
| 2 | Michal | 81 | ... | 81 | 78 |
| ... | ... | ... | ... | ... | ... |
| 11 | Tom | 98 | ... | 92 | 80 |
| 12 | Adi | 76 | ... | 84 | 70 |
12 rows × 8 columns
לחלופין, נוכל לבצע השמה למשתנה שמכיל את הטבלה המקורית ולגרום לו להצביע לטבלה החדשה:
df=df.drop(12)
display(df)
| Name | Programming | ... | Planet Survival | Art | |
|---|---|---|---|---|---|
| 1 | Nadav | 61 | ... | 52 | 88 |
| 2 | Michal | 81 | ... | 81 | 78 |
| ... | ... | ... | ... | ... | ... |
| 10 | Yaniv | 100 | ... | 88 | 90 |
| 11 | Tom | 98 | ... | 92 | 80 |
11 rows × 8 columns
בהמשך נלמד על דרכים נוספות להסרת שורות ועמודות מטבלה
הוספת שורות ועמודות#
נחזור שוב לטבלה המקורית שלנו:
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
הוספת שורה#
כדי להוסיף שורה או עמודה חדשה ל-DataFrame קיים (במקרה שלנו, שורה מייצגת סטודנט חדש), ניצור DataFrame המכיל שורה או עמודה בודדת, ונשרשר אותה לסוף הטבלה באמצעות פונקצית pd.concat.
פונקציה זו יודעת לחבר מספר טבלאות - המועברות בtuple או בlist כפרמטר ראשון לפונקציה - בדרכים שונות. נרחיב על מגוון פעולות חיבור הטבלאות שניתן לעשות באמצעות concat ביחידות הבאות.
לצורך הוספת שורה, נשתמש בפונקציה pd.concat על מנת ליצור טבלה חדשה, שהיא למעשה בין הטבלה המקורית ובין הטבלה בעלת השורה הבודדת שיצרנו.
new_student = [{'Name':"Dana",'Programming':76.0,'Marine Biology':65.0,'Stellar Cartography':98.0,'Math':8.07,
'History':65.0,'Planet Survival':89.0,'Art':100.0}]
pd.DataFrame(new_student)
df_new = pd.concat((df, pd.DataFrame(new_student)))
display(df_new)
| Name | Programming | ... | Planet Survival | Art | |
|---|---|---|---|---|---|
| 0 | Yael | 50.0 | ... | 65.0 | 91.0 |
| 1 | Nadav | 61.0 | ... | 52.0 | 88.0 |
| ... | ... | ... | ... | ... | ... |
| 12 | Adi | 76.0 | ... | 84.0 | 70.0 |
| 0 | Dana | 76.0 | ... | 89.0 | 100.0 |
14 rows × 8 columns
שימו לב
לשורה הראשונה והאחרונה יש אותו שם (0). עניין זה יכול ליצור לנו הרבה בפעולות שנרצה לעשות בהמשך (כמו גישה שורות לפי שם).
על מנת להתגבר על בעיה זו, יש להוסיף ignore_index=True לפונקציה concat. פרמטר זה למעשה “מאפס” את שמות הטבלה ומאתחלן לאידקס רץ מ0 כפי שנעשה כאשר יוצרים טבלה חדשה לחלוטין.
לאחר הוספת הפרמטר, הטבלה שחוזרת מconcat תראה כך:
df_new = pd.concat((df, pd.DataFrame(new_student)), ignore_index=True)
display(df_new)
| Name | Programming | ... | Planet Survival | Art | |
|---|---|---|---|---|---|
| 0 | Yael | 50.0 | ... | 65.0 | 91.0 |
| 1 | Nadav | 61.0 | ... | 52.0 | 88.0 |
| ... | ... | ... | ... | ... | ... |
| 12 | Adi | 76.0 | ... | 84.0 | 70.0 |
| 13 | Dana | 76.0 | ... | 89.0 | 100.0 |
14 rows × 8 columns
הוספת עמודה#
נשתמש בטכניקה דומה על מנת להוסיף עמודה בסוף הטבלה.
מכיוון שמדובר בעמודה, נשנה בפונקציה concat את הערך של הפרמטר לaxis=1. פרמטר מנחה את הפונקציה לפעול על ציר העמודות, או במילים אחרות, להוסיף עמודה.
בדוגמא להלן השתמשנו בconcat על מנת להוסיף את המקצוע גלישה:
inputFileName = "files/StudentsGrades.csv"
df = pd.read_csv(inputFileName)
new_grade = {"Surfing" : [60, 65, 70, 75, 80, 85, 90, 95, 99, 82, 50, 52, 70]}
df_new = pd.concat((df, pd.DataFrame(new_grade)), axis=1)
display(df_new)
| Name | Programming | ... | Art | Surfing | |
|---|---|---|---|---|---|
| 0 | Yael | 50 | ... | 91 | 60 |
| 1 | Nadav | 61 | ... | 88 | 65 |
| ... | ... | ... | ... | ... | ... |
| 11 | Tom | 98 | ... | 80 | 52 |
| 12 | Adi | 76 | ... | 70 | 70 |
13 rows × 9 columns
הערה
במקרה זה אין צורך לפרט ignore_index=True מכיוון שאנו מוסיפים עמודה, ואנו מניחים שאין עמודה בעלת שם זהה בטבלה.
כפי שראינו בהסרת שורות ועמודות, ניתן לבצע השמה למשתנה הטבלה המקורית על מנת להפנות את המשתנה המקורי לטבלה החדשה:
df = pd.concat((df, pd.DataFrame(new_grade)), axis=1)
display(df)
| Name | Programming | ... | Art | Surfing | |
|---|---|---|---|---|---|
| 0 | Yael | 50 | ... | 91 | 60 |
| 1 | Nadav | 61 | ... | 88 | 65 |
| ... | ... | ... | ... | ... | ... |
| 11 | Tom | 98 | ... | 80 | 52 |
| 12 | Adi | 76 | ... | 70 | 70 |
13 rows × 9 columns
השמה בloc/iloc/[]#
ניתן גם להוסיף או לעדכן שורות ועמודות בטבלה במקורית באמצעות השמה ישירה לפי שם או מיקום. בדומה לגישה ברשימות ובמילונים, גם כאן סוג האינדקס קובע את ההתנהגות:
בעת שימוש ב־
loc(או ב[]עם שם עמודה), יתבצע עדכון או יצירה, בדומה למילון:אם העמודה שצוינה לא קיימת, תתווסף עמודה חדשה לטבלה.
אם הייתה עמודה בשם זה, הערכים שבה יוחלפו בהתאם לערכים החדשים.
לעומת זאת, בעבודה עם
iloc, לא ניתן ליצור עמודות חדשות, אלא רק לעדכן ערכים קיימים לפי מיקומם. מדובר בהתנהגות דומה להתנהגות של רשימה בפייתון. ניתן לבצעl[i]=valueרק אםiהוא כבר אינדקס חוקי ברשימה.
לדוגמה, הקוד הבא יוסיף עמודה חדשה בשם “Grade Average” שתכיל את ממוצע הציונים בכל סטודנט בטבלה:
input_file_name = "files/StudentsGrades.csv"
df = pd.read_csv(input_file_name)
df["Grade Average"]=df.iloc[:,1:].mean(axis=1)
display(df)
| Name | Programming | ... | Art | Grade Average | |
|---|---|---|---|---|---|
| 0 | Yael | 50 | ... | 91 | 68.428571 |
| 1 | Nadav | 61 | ... | 88 | 70.142857 |
| ... | ... | ... | ... | ... | ... |
| 11 | Tom | 98 | ... | 80 | 91.714286 |
| 12 | Adi | 76 | ... | 70 | 75.571429 |
13 rows × 9 columns