> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# كيفية الاستعلام عن إطارات بيانات Pandas باستخدام chDB

> تعرّف على كيفية الاستعلام عن إطارات بيانات Pandas باستخدام chDB

تُعد [Pandas](https://pandas.pydata.org/) مكتبة شائعة لمعالجة البيانات وتحليلها في Python.
في الإصدار 2 من chDB، حسّنّا أداء الاستعلام على إطارات بيانات Pandas وطرحنا دالة الجدول `Python`.
في هذا الدليل، سنتعلّم كيفية الاستعلام عن Pandas باستخدام دالة الجدول `Python`.

<div id="setup">
  ## التهيئة
</div>

لنبدأ أولًا بإنشاء بيئة افتراضية:

```bash theme={null}
python -m venv .venv
source .venv/bin/activate
```

والآن سنقوم بتثبيت chDB.
تأكد من أن لديك الإصدار 2.0.2 أو أحدث:

```bash theme={null}
pip install "chdb>=2.0.2"
```

والآن سنثبّت Pandas ومكتبتين إضافيتين:

```bash theme={null}
pip install pandas requests ipython
```

سنستخدم `ipython` لتشغيل الأوامر في بقية الدليل، ويمكنك تشغيله بتنفيذ:

```bash theme={null}
ipython
```

يمكنك أيضًا استخدام هذا الكود في سكربت Python أو في دفتر Jupyter المفضل لديك.

<div id="creating-a-pandas-dataframe-from-a-url">
  ## إنشاء Pandas DataFrame من عنوان URL
</div>

سنُجري query لبعض البيانات من [مستودع StatsBomb على GitHub](https://github.com/statsbomb/open-data/tree/master?tab=readme-ov-file).
لنبدأ أولًا باستيراد requests وpandas:

```python theme={null}
import requests
import pandas as pd
```

ثم سنحمّل أحد ملفات المباريات بتنسيق JSON إلى DataFrame:

```python theme={null}
response = requests.get(
  "https://raw.githubusercontent.com/statsbomb/open-data/master/data/matches/223/282.json"
)
matches_df = pd.json_normalize(response.json(), sep='_')
```

لنلقِ نظرة على البيانات التي سنتعامل معها:

```python theme={null}
matches_df.iloc[0]
```

```text theme={null}
match_id                                                                  3943077
match_date                                                             2024-07-15
kick_off                                                             04:15:00.000
home_score                                                                      1
away_score                                                                      0
match_status                                                            available
match_status_360                                                      unscheduled
last_updated                                           2024-07-15T15:50:08.671355
last_updated_360                                                             None
match_week                                                                      6
competition_competition_id                                                    223
competition_country_name                                            South America
competition_competition_name                                         Copa America
season_season_id                                                              282
season_season_name                                                           2024
home_team_home_team_id                                                        779
home_team_home_team_name                                                Argentina
home_team_home_team_gender                                                   male
home_team_home_team_group                                                    None
home_team_country_id                                                           11
home_team_country_name                                                  Argentina
home_team_managers              [{'id': 5677, 'name': 'Lionel Sebastián Scalon...
away_team_away_team_id                                                        769
away_team_away_team_name                                                 Colombia
away_team_away_team_gender                                                   male
away_team_away_team_group                                                    None
away_team_country_id                                                           49
away_team_country_name                                                   Colombia
away_team_managers              [{'id': 5905, 'name': 'Néstor Gabriel Lorenzo'...
metadata_data_version                                                       1.1.0
metadata_shot_fidelity_version                                                  2
metadata_xy_fidelity_version                                                    2
competition_stage_id                                                           26
competition_stage_name                                                      Final
stadium_id                                                                   5337
stadium_name                                                    Hard Rock Stadium
stadium_country_id                                                            241
stadium_country_name                                     United States of America
referee_id                                                                   2638
referee_name                                                        Raphael Claus
referee_country_id                                                             31
referee_country_name                                                       Brazil
Name: 0, dtype: object
```

بعد ذلك، سنحمّل أحد ملفات JSON الخاصة بالأحداث، وسنضيف أيضًا عمودًا باسم `match_id` إلى كائن DataFrame هذا:

```python theme={null}
response = requests.get(
  "https://raw.githubusercontent.com/statsbomb/open-data/master/data/events/3943077.json"
)
events_df = pd.json_normalize(response.json(), sep='_')
events_df["match_id"] = 3943077
```

ومرةً أخرى، دعونا نلقِ نظرةً على الصف الأول:

```python theme={null}
with pd.option_context("display.max_rows", None):
    first_row = events_df.iloc[0]
    non_nan_columns = first_row[first_row.notna()].T
    display(non_nan_columns)
```

```text theme={null}
id                                   279b7d66-92b5-4daa-8ff6-cba8fce271d9
index                                                                   1
period                                                                  1
timestamp                                                    00:00:00.000
minute                                                                  0
second                                                                  0
possession                                                              1
duration                                                              0.0
type_id                                                                35
type_name                                                     Starting XI
possession_team_id                                                    779
possession_team_name                                            Argentina
play_pattern_id                                                         1
play_pattern_name                                            Regular Play
team_id                                                               779
team_name                                                       Argentina
tactics_formation                                                   442.0
tactics_lineup          [{'player': {'id': 6909, 'name': 'Damián Emili...
match_id                                                          3943077
Name: 0, dtype: object
```

<div id="querying-pandas-dataframes">
  ## الاستعلام عن Pandas DataFrames
</div>

بعد ذلك، لنرَ كيف نستعلم عن وحدات DataFrame هذه باستخدام chDB.
سنستورد المكتبة:

```python theme={null}
import chdb
```

يمكننا إجراء استعلامات على إطارات بيانات Pandas باستخدام دالة الجدول `Python`:

```sql theme={null}
SELECT *
FROM Python(<name-of-variable>)
```

إذًا، إذا أردنا سرد الأعمدة في `matches_df`، يمكننا كتابة ما يلي:

```python theme={null}
chdb.query("""
DESCRIBE Python(matches_df)
SETTINGS describe_compact_output=1
""", "DataFrame")
```

```text theme={null}
                              name    type
0                         match_id   Int64
1                       match_date  String
2                         kick_off  String
3                       home_score   Int64
4                       away_score   Int64
5                     match_status  String
6                 match_status_360  String
7                     last_updated  String
8                 last_updated_360  String
9                       match_week   Int64
10      competition_competition_id   Int64
11        competition_country_name  String
12    competition_competition_name  String
13                season_season_id   Int64
14              season_season_name  String
15          home_team_home_team_id   Int64
16        home_team_home_team_name  String
17      home_team_home_team_gender  String
18       home_team_home_team_group  String
19            home_team_country_id   Int64
20          home_team_country_name  String
21              home_team_managers  String
22          away_team_away_team_id   Int64
23        away_team_away_team_name  String
24      away_team_away_team_gender  String
25       away_team_away_team_group  String
26            away_team_country_id   Int64
27          away_team_country_name  String
28              away_team_managers  String
29           metadata_data_version  String
30  metadata_shot_fidelity_version  String
31    metadata_xy_fidelity_version  String
32            competition_stage_id   Int64
33          competition_stage_name  String
34                      stadium_id   Int64
35                    stadium_name  String
36              stadium_country_id   Int64
37            stadium_country_name  String
38                      referee_id   Int64
39                    referee_name  String
40              referee_country_id   Int64
41            referee_country_name  String
```

يمكننا بعد ذلك معرفة الحكام الذين أداروا أكثر من مباراة واحدة بكتابة الاستعلام التالي:

```python theme={null}
chdb.query("""
SELECT referee_name, count() AS count
FROM Python(matches_df)
GROUP BY ALL
HAVING count > 1
ORDER BY count DESC
""", "DataFrame")
```

```text theme={null}
                    referee_name  count
0  César Arturo Ramos Palazuelos      3
1               Maurizio Mariani      3
2               Piero Maza Gomez      3
3     Mario Alberto Escobar Toca      2
4  Wilmar Alexander Roldán Pérez      2
5          Jesús Valenzuela Sáez      2
6         Wilton Pereira Sampaio      2
7                  Darío Herrera      2
8                 Andrés Matonte      2
9                  Raphael Claus      2
```

الآن، لنستعرض `events_df`.

```python theme={null}
chdb.query("""
SELECT pass_recipient_name, count()
FROM Python(events_df)
WHERE type_name = 'Pass' AND pass_recipient_name <> ''
GROUP BY ALL
ORDER BY count() DESC
LIMIT 10
""", "DataFrame")
```

```text theme={null}
               pass_recipient_name  count()
0            Davinson Sánchez Mina       76
1  Ángel Fabián Di María Hernández       64
2              Alexis Mac Allister       62
3                   Enzo Fernandez       57
4      James David Rodríguez Rubio       56
5      Johan Andrés Mojica Palacio       55
6           Rodrigo Javier De Paul       54
7     Jefferson Andrés Lerma Solís       53
8        Jhon Adolfo Arias Andrade       52
9  Carlos Eccehomo Cuesta Figueroa       50
```

<div id="joining-pandas-dataframes">
  ## ربط إطارات بيانات Pandas
</div>

يمكننا أيضًا ضمّ إطارات البيانات معًا في استعلام.
على سبيل المثال، للحصول على لمحة عامة عن المباراة، يمكننا كتابة الاستعلام التالي:

```python theme={null}
chdb.query("""
SELECT home_team_home_team_name, away_team_away_team_name, home_score, away_score,
       countIf(type_name = 'Pass' AND possession_team_id=home_team_home_team_id) AS home_passes,
       countIf(type_name = 'Pass' AND possession_team_id=away_team_away_team_id) AS away_passes,
       countIf(type_name = 'Shot' AND possession_team_id=home_team_home_team_id) AS home_shots,
       countIf(type_name = 'Shot' AND possession_team_id=away_team_away_team_id) AS away_shots
FROM Python(matches_df) AS matches
JOIN Python(events_df) AS events ON events.match_id = matches.match_id
GROUP BY ALL
LIMIT 5
""", "DataFrame").iloc[0]
```

```text theme={null}
home_team_home_team_name    Argentina
away_team_away_team_name     Colombia
home_score                          1
away_score                          0
home_passes                       527
away_passes                       669
home_shots                         11
away_shots                         19
Name: 0, dtype: object
```

<div id="populating-a-table-from-a-dataframe">
  ## ملء جدول انطلاقًا من DataFrame
</div>

يمكننا أيضًا إنشاء جداول ClickHouse وملؤها انطلاقًا من DataFrames.
إذا أردنا إنشاء جدول في chDB، فعلينا استخدام Stateful Session API.

لنستورد وحدة session:

```python theme={null}
from chdb import session as chs
```

هيّئ جلسة:

```python theme={null}
sess = chs.Session()
```

بعد ذلك، سننشئ قاعدة بيانات:

```python theme={null}
sess.query("CREATE DATABASE statsbomb")
```

بعد ذلك، أنشئ جدول `events` اعتمادًا على `events_df`:

```python theme={null}
sess.query("""
CREATE TABLE statsbomb.events ORDER BY id AS
SELECT * 
FROM Python(events_df)
""")
```

يمكننا بعد ذلك تشغيل الاستعلام الذي يُرجع اللاعب الأكثر استقبالًا للتمريرات:

```python theme={null}
sess.query("""
SELECT pass_recipient_name, count()
FROM statsbomb.events
WHERE type_name = 'Pass' AND pass_recipient_name <> ''
GROUP BY ALL
ORDER BY count() DESC
LIMIT 10
""", "DataFrame")
```

```text theme={null}
               pass_recipient_name  count()
0            Davinson Sánchez Mina       76
1  Ángel Fabián Di María Hernández       64
2              Alexis Mac Allister       62
3                   Enzo Fernandez       57
4      James David Rodríguez Rubio       56
5      Johan Andrés Mojica Palacio       55
6           Rodrigo Javier De Paul       54
7     Jefferson Andrés Lerma Solís       53
8        Jhon Adolfo Arias Andrade       52
9  Carlos Eccehomo Cuesta Figueroa       50
```

<div id="joining-a-pandas-dataframe-and-table">
  ## الربط بين Pandas DataFrame وجدول
</div>

أخيرًا، يمكننا أيضًا تحديث استعلام الربط لربط `matches_df` DataFrame بجدول `statsbomb.events`:

```python theme={null}
sess.query("""
SELECT home_team_home_team_name, away_team_away_team_name, home_score, away_score,
       countIf(type_name = 'Pass' AND possession_team_id=home_team_home_team_id) AS home_passes,
       countIf(type_name = 'Pass' AND possession_team_id=away_team_away_team_id) AS away_passes,
       countIf(type_name = 'Shot' AND possession_team_id=home_team_home_team_id) AS home_shots,
       countIf(type_name = 'Shot' AND possession_team_id=away_team_away_team_id) AS away_shots
FROM Python(matches_df) AS matches
JOIN statsbomb.events AS events ON events.match_id = matches.match_id
GROUP BY ALL
LIMIT 5
""", "DataFrame").iloc[0]
```

```text theme={null}
home_team_home_team_name    Argentina
away_team_away_team_name     Colombia
home_score                          1
away_score                          0
home_passes                       527
away_passes                       669
home_shots                         11
away_shots                         19
Name: 0, dtype: object
```
