לפעמים נרצה לעשות פעולות מתמטיות על נתונים ב- Pandas, לרוב נתונים שנמצאים ב- Series.
Pandas מאפשרת לנו כמה קיצורי דרך שמקלים עלינו את העבודה בחישובים הללו.

פעולות מתמטיות בין סדרות

בואו נאתחל שתי סדרות אשר מכילות ערכים מספריים:

import pandas as pd

num_list1 = pd.Series([7, 3, 6, 2, 8])
num_list2 = pd.Series([14, 6, 3, 2, 10])

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

num_list1 = pd.Series([7, 3, 6, 2, 8])
num_list2 = pd.Series([14, 6, 3, 2, 10])

sum_list = num_list1 + num_list2
print(sum_list)

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

import pandas as pd

num_list1 = pd.Series([7, 3, 6, 2, 8])
num_list2 = pd.Series([14, 6, 3, 2, 10])

sum_list = num_list1 + num_list2
dif_list = num_list1 - num_list2
mul_list = num_list1 * num_list2
div_list = num_list1 / num_list2
mod_list = num_list1 % num_list2
print(sum_list)
print(dif_list)
print(mul_list)
print(div_list)
print(mod_list)

פעולות מתמטיות על סדרות בעלות אינדקסים שונים

ומה אם הסדרות אינן שוות באורכן? במקרה כזה, Pandas תיצור סדרה באורך הסדרה הארוכה, אך האיברים שלא היה להם בן זוג יקבלו את הערך NaN. זה קיצור של not a number וכך מסמנים בפייתון משהו שאמור להיות מספר אך אין לו ערך בעל משמעות.

num_list1 = pd.Series([7, 3, 6, 2, 8])
num_list2 = pd.Series([14, 6, 3, 2])

sum_list = num_list1 + num_list2

print(sum_list)

שימו לב שהאיבר באינדקס 4 קיבל את הערך NaN. זה כיוון שאינדקס 4 קיים רק באחת מהסדרות שחיברנו.

חשוב להבין שכאשר Pandas מבצעת פעולה בין שתי סדרות, היא מקשרת בין זוגות של איברים לפי שמות האיברים (שמות השורות שלהם). ברירת המחדל לשם של איבר הוא האינדקס שלו, לכן אם לא הגדרנו שמות אחרים, האיבר במיקום “0” יחובר עם האיבר במיקום “0” בסדרה השנייה, וכך עבור כל האיברים. אבל כמו שלמדנו, אנו יכולים לקבוע בעצמנו שמות אחרים. מה יקרה אם איבר כלשהו יופיע רק באחת הסדרות?

num_list1 = pd.Series({"bubu": 7, "bobi": 3, "bibu": 6})
num_list2 = pd.Series({"babi": 9, "bubu": 7, "bobi": 3})

sum_list = num_list1 + num_list2
print(sum_list)

במקרה הזה, אנחנו רואים שהאיברים חוברו לפי שמותיהם ולא לפי האינדקסים שלהם. אם שם כלשהו קיים רק באחת הסדרות, הוא יופיע בסדרת הסכום, אך הערך שיקבל יהיה NaN.

קביעת ערך של ברירת מחדל בפעולות מתמטיות בין סדרות

לפעמים, הערך NaN אינו רצוי. יכול להיות שבדוגמה של הסכום, נרצה להתייחס לערכים חסרים כ- 0, כך שאם, למשל, הערך של האיבר ‘bob’ בסדרה הראשונה הוא 7, ואילו בסדרה השנייה הוא לא קיים, גם איבר הסכום יהיה 7.

לצורך כך, אפשר להשתמש להשתמש בפונקציה add במקום באופרטור החיבור. פונקציה זו יכולה לקבל את הפרמטר האופציונלי fill_value, אשר יקבע מה הערך שיינתן לערכים שלא קיימים בסדרה. בואו ננסה לקבוע את ערכו ל-0:

num_list1 = pd.Series({"bubu": 7, "bobi": 3, "bibu": 6})
num_list2 = pd.Series({"babi": 9, "bubu": 7, "bobi": 3})

sum_list = num_list1.add(num_list2, fill_value=0)
print(sum_list)

ואנו רואים שכעת האיברים החסרים קיבלו את הערך NaN ובסדרת הסכום התקבל הערך של הסדרה שאכן סיפקה ערך תקין.

פעולות מתמטיות בין Series לבין מספר

באופן דומה לביצוע פעולות חשבוניות בין סדרות, ב- Pandas אפשר לבצע פעולות חשבוניות גם בין סדרה למספר. בואו נניח למשל שיש לנו Series של ציונים של תלמידים במבחן.

grades = pd.Series([85, 79, 95, 86, 90])

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

grades = pd.Series([85, 79, 95, 86, 90])
factor = pd.Series([5]*grades.size)
final_grades = grades + factor
print(final_grades)

אך ישנה דרך פשוטה יותר. אפשר פשוט להוסיף את ערכו של הפקטור, כמספר, לסדרה. Pandas תחבר את המספר הזה לכל אחד מערכי הסדרה כך שנקבל את הסדרה לאחר הפקטור.

grades = pd.Series([85, 79, 95, 86, 90])
factor = 5
final_grades = grades + factor
print(final_grades)

ואנו רואים שהתקבלה בדיוק אותה תוצאה כמו קודם.