# Pandas — DataFrame, Series ו-read_csv📖 שיעור

## מה זה?

ביחידת Kafka כתבנו Python בסיסי לראשונה. עכשיו — הכלי המרכזי לעיבוד נתונים בפייתון: Pandas. במקום לקרוא CSV ל-`List<(string, string)>` ולעבד ידנית עם לולאות (כמו בפרויקט ה-Naive Bayes ב-C#), Pandas נותן מבנה נתונים טבלאי (`DataFrame`) עם פעולות מובנות — סינון, מיון, קיבוץ — הרבה יותר תמציתי מלולאות ידניות, ומותאם במיוחד לניתוח נתונים בקנה מידה גדול.

## מילות מפתח שחשוב לזכור

• `DataFrame` — טבלה דו-ממדית בזיכרון (שורות ועמודות), המבנה המרכזי של Pandas — דומה ל-`DbSet<T>` מיחידת EF Core, אך בלי DB מאחוריו

• `Series` — עמודה בודדת מתוך `DataFrame`, או רשימה חד-ממדית עם אינדקס

• `read_csv`/`read_json`/`read_sql` — פונקציות שטוענות נתונים ישירות ל-DataFrame ממקורות שונים

• `.iloc[]` — גישה לפי **מיקום** מספרי (אינדקס), כמו `array[i]`

• `.loc[]` — גישה לפי **תווית** (שם עמודה/אינדקס), לא מיקום

```python
import pandas as pd

# Creating a DataFrame manually
data = {
    "Name": ["Dana", "Avi", "Rotem"],
    "Age": [25, 30, 22],
    "Score": [95, 88, 76]
}
df = pd.DataFrame(data)

# Loading from an external source — much more common in practice
df = pd.read_csv("students.csv")
df = pd.read_json("students.json")
```

```python
# Series — a single column
names = df["Name"]          # Series with all the names
print(type(names))          # <class 'pandas.core.series.Series'>

# iloc — by numeric position
first_row = df.iloc[0]      # the first row, by position — like array[0]

# loc — by label
dana_age = df.loc[0, "Age"] # index 0, Age column
```

```python
# Checking the data — always the first step before processing
df.head()      # the first 5 rows
df.info()      # column types, count of non-null values
df.describe()  # basic statistics: mean, min, max, etc. for numeric columns
```

## הסבר עיקרי

`DataFrame` הוא "טבלת SQL בזיכרון" — כל עמודה יכולה להיות בטיפוס שונה (מספר, טקסט, תאריך), בדיוק כמו טבלת DB, אבל הכל חי בזיכרון פייתון, בלי צורך בשרת DB. זו הסיבה ש-Pandas כל כך נפוץ לניתוח נתונים חד-פעמי או אקספלורטיבי — אין overhead של חיבור/שאילתה, רק טעינה וניתוח מיידי.

`.iloc` מול `.loc` — ההבדל הזה מבלבל מתחילים תדיר: `.iloc[0]` תמיד אומר "השורה הראשונה לפי מיקום" (בדיוק כמו אינדקס מערך מ-C#). `.loc[0]` אומר "השורה עם **תווית** אינדקס 0" — שבד"כ (כשה-DataFrame לא מסונן/ממוין) זהה ל-`.iloc[0]`, אבל **לא תמיד** — אחרי סינון, האינדקסים המקוריים נשארים, כך ש-`.loc[0]` עשוי "לא להיות שם" בכלל אם השורה הראשונה שסוננה החוצה.

`head`/`info`/`describe` הם תמיד הצעד הראשון — לפני כל עיבוד, בודקים: איך הנתונים נראים (`head`), אילו טיפוסים ואיפה חסרים ערכים (`info`), ומה הטווחים הסטטיסטיים (`describe`). דילוג על השלב הזה ("קפיצה ישר לעיבוד") הוא טעות נפוצה שמובילה לגילוי בעיות נתונים מאוחר מדי.

## יתרונות

`DataFrame` נותן כלים אנליטיים עוצמתיים בשורת קוד אחת (סינון, מיון, סטטיסטיקה); `read_csv`/`read_json`/`read_sql` טוענים ממקורות שונים בממשק אחיד; `head`/`info`/`describe` נותנים תמונת מצב מהירה על איכות הנתונים לפני עיבוד.

## חסרונות

DataFrame גדול מאוד עלול לצרוך זיכרון רב (כל הנתונים בזיכרון RAM, לא בזרימה); `.iloc`/`.loc` דומים מספיק בשם כדי לבלבל בין מיקום לתווית, טעות נפוצה במיוחד למתחילים.

## נקודות חשובות

• `DataFrame` = טבלה דו-ממדית; `Series` = עמודה בודדת/רשימה חד-ממדית עם אינדקס

• `.iloc` = לפי מיקום מספרי; `.loc` = לפי תווית (עלולים להיות שונים אחרי סינון/מיון)

• `read_csv`/`read_json`/`read_sql` טוענים נתונים ממקורות שונים לDataFrame אחיד

• `head`/`info`/`describe` הם תמיד הצעד הראשון לפני עיבוד — לא לדלג עליו

## טעויות נפוצות

• לבלבל בין `.iloc[0]` (מיקום) ל-`.loc[0]` (תווית) — במיוחד אחרי `sort_values`/`filter` שמשנים את סדר האינדקסים בפועל

• לקפוץ ישר לעיבוד נתונים בלי `info`/`describe` קודם, ולגלות בעיות (ערכים חסרים, טיפוס שגוי) מאוחר מדי

• לטעון DataFrame ענק שלם לזיכרון כשמספיק חלק ממנו (`nrows` ב-`read_csv`)

## סיכום

`DataFrame` הוא המבנה המרכזי של Pandas — טבלה דו-ממדית בזיכרון, נטענת בקלות ממקורות שונים (`read_csv`/`read_json`/`read_sql`). `Series` היא עמודה בודדת מתוכו. `.iloc` ניגש לפי מיקום מספרי, `.loc` לפי תווית — הבדל שחשוב לזכור במיוחד אחרי סינון/מיון. `head`/`info`/`describe` הם שגרת הבדיקה הראשונית שתמיד קודמת לעיבוד נתונים אמיתי.

## דוקומנטציה רשמית

[Pandas — Documentation](https://pandas.pydata.org/docs/)

---

## תרגילים

### תרגיל 1 — יצירה וטעינה

**המשימה:** צרו קובץ CSV קטן (5 שורות, 3 עמודות) וטענו אותו עם `read_csv`. הריצו `head()`, `info()`, `describe()` והסבירו בקצרה מה כל אחד מציג.

**בדיקה:** שלושת הפלטים מוצגים נכון ותואמים לנתונים שבקובץ.

### תרגיל 2 — iloc מול loc

**המשימה:** צרו DataFrame עם 5 שורות, סננו אותו (רק שורות עם ערך מסוים), והשוו את התוצאה של `.iloc[0]` מול `.loc[0]` על ה-DataFrame המסונן.

**בדיקה:** התוצאות שונות (או שוות רק במקרה) — הדגמה מוחשית להבדל בין מיקום לתווית.

---

## פרויקט מסכם

**המשימה:** טענו קובץ CSV בגודל בינוני (20+ שורות) עם נתוני מכירות (`Date`, `Product`, `Amount`), ובצעו סקירה ראשונית מלאה.

**דרישות:**
1. `read_csv` לטעינת הנתונים
2. `info()` לבדיקת טיפוסי עמודות וערכים חסרים
3. `describe()` לסטטיסטיקה על עמודת `Amount`
4. שליפת שורה בודדת עם `.loc` ועם `.iloc`, והשוואה בין השתיים

**בדיקה:** כל הפעולות רצות בלי שגיאה, והפלט של כל אחת מוסבר בקצרה (איזה מידע היא נותנת).

## מה בפרק הבא

בפרק הבא — **סינון ומיון**: איך לבחור בדיוק את השורות שרוצים ולסדר אותן, הצעד הבא אחרי הסקירה הראשונית.
