שימו לב: על מנת להריץ את התאים ב-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