{"checkpoints":{"s-pda-1":[{"q":"<p>ماذا يطبع هذا الكود؟</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">prices </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> {</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Desk Mat XL\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">29</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Laptop Stand\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">: </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">49</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">}</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">prices[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Desk Mat XL\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> prices.get(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Desk Mat XL\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 1</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">len</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(prices), prices[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Desk Mat XL\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">2 30</code>","why":"صحيح. المفتاح موجود أصلًا، فتعيد <code dir=\"ltr\">.get()</code> القيمة 29، ويُضاف إليها واحد، ويبقى في القاموس مفتاحان."},{"text":"<code dir=\"ltr\">3 30</code>","why":"الإسناد إلى مفتاح موجود يحدّثه؛ ولا يضيف مُدخلًا ثانيًا بالاسم نفسه."},{"text":"<code dir=\"ltr\">2 1</code>","why":"تعيد <code dir=\"ltr\">.get()</code> القيمة المخزّنة، 29، لأن المفتاح موجود. القيمة الافتراضية 0 لا تُستخدم إلا مع المفاتيح المفقودة."},{"text":"خطأ <code dir=\"ltr\">KeyError</code>","why":"كل مفتاح يقرؤه الكود بالأقواس المربعة موجود، و<code dir=\"ltr\">.get()</code> لا تُطلق خطأً لمفتاح مفقود أصلًا."}],"answer":0},{"q":"<p>تعيد دالة كتبها زميلك <code dir=\"ltr\">3.3333333333333335</code> لـ <code dir=\"ltr\">average([10, 20, 30])</code> بدلًا من <code dir=\"ltr\">20.0</code>. ما الخطأ؟</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">def</span><span style=\"color:#8250DF;--shiki-dark:#D2A8FF\"> average</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(values):</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">    total </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">    for</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> v </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">in</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> values:</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">        total </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">+=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> v</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">        return</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> total </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> len</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(values)</span></span></code></pre></div>\n","options":[{"text":"يجب أن يبدأ <code dir=\"ltr\">total</code> من 1.","why":"البدء من 1 سيجعل كل متوسط أعلى قليلًا؛ ولن يفسّر نتيجة مبنية على القيمة الأولى وحدها."},{"text":"<code dir=\"ltr\">len(values)</code> تعدّ الحروف بدلًا من العناصر.","why":"الدالة <code dir=\"ltr\">len</code> على قائمة تعدّ عناصرها، وهي هنا 3."},{"text":"السطر <code dir=\"ltr\">return</code> مُزاح داخل الحلقة، فتعود الدالة بعد إضافة القيمة الأولى.","why":"صحيح. في الدورة الأولى يكون <code dir=\"ltr\">total</code> يساوي 10، فتعيد الدالة فورًا 10 / 3. إعادة <code dir=\"ltr\">return</code> إلى مستوى الدالة تصلح ذلك."},{"text":"لا تستطيع Python قسمة الأعداد الصحيحة، فتعيد القيمة الأولى.","why":"تقسم Python الأعداد الصحيحة بـ <code dir=\"ltr\">/</code> وتعيد عددًا عشريًا."}],"answer":2},{"q":"<p>أيّ f-string تطبع <code dir=\"ltr\">Share: 12.5%</code> حين تكون <code dir=\"ltr\">share = 0.125</code>؟</p>","options":[{"text":"<code dir=\"ltr\">f&quot;Share: {share:.1f}%&quot;</code>","why":"هذه تنسّق 0.125 بمنزلة عشرية واحدة، فتعطي <code dir=\"ltr\">0.1%</code>. المواصفة <code dir=\"ltr\">f</code> لا تضرب في 100."},{"text":"<code dir=\"ltr\">f&quot;Share: {share:%}&quot;</code>","why":"المواصفة <code dir=\"ltr\">%</code> تضرب في 100، لكنها تستخدم ست منازل عشرية افتراضيًا: <code dir=\"ltr\">12.500000%</code>."},{"text":"<code dir=\"ltr\">f&quot;Share: {share:,.2f}%&quot;</code>","why":"هذه تطبع <code dir=\"ltr\">0.12%</code>: منزلتان عشريتان من الكسر الخام."},{"text":"<code dir=\"ltr\">f&quot;Share: {share:.1%}&quot;</code>","why":"صحيح. المواصفة <code dir=\"ltr\">%</code> تضرب في 100 وتضيف علامة النسبة المئوية؛ و<code dir=\"ltr\">.1</code> تحتفظ بمنزلة عشرية واحدة."}],"answer":3},{"q":"<p>تتوقّف حلقة تمرّ على الصفوف بالخطأ <code dir=\"ltr\">TypeError: unsupported operand type(s) for +: 'int' and 'str'</code> في السطر <code dir=\"ltr\">total = total + row[&quot;quantity&quot;]</code>. ما الإصلاح الأرجح؟</p>","options":[{"text":"أعِد تسمية <code dir=\"ltr\">total</code> إلى شيء آخر.","why":"الاسم سليم؛ الخطأ يتعلّق بنوعي القيمتين اللتين تُجمعان."},{"text":"حوّل الكمية أولًا: <code dir=\"ltr\">total = total + int(row[&quot;quantity&quot;])</code>.","why":"صحيح. وصلت الكمية نصًا، ولا تجمع Python أبدًا نصًا مع رقم ضمنيًا."},{"text":"غلّف السطر بـ <code dir=\"ltr\">try</code> / <code dir=\"ltr\">except TypeError</code> وتخطَّ الصف.","why":"كل الكميات وصلت نصوصًا، فسيُتخطّى كل صف ويبقى المجموع 0، دون أي رسالة خطأ تنبّهك."},{"text":"ابدأ <code dir=\"ltr\">total</code> بـ <code dir=\"ltr\">&quot;&quot;</code> بدلًا من 0.","why":"هذا سيلصق الكميات ببعضها كنص، فيعطي شيئًا مثل <code dir=\"ltr\">&quot;121&quot;</code> بدلًا من رقم."}],"answer":1},{"q":"<p><code dir=\"ltr\">totals = [65.0, 18.0, 72.0]</code>. ماذا تنتج <code dir=\"ltr\">[t &gt; 50 for t in totals]</code>؟</p>","options":[{"text":"<code dir=\"ltr\">[True, False, True]</code>","why":"صحيح. التعبير الذي قبل <code dir=\"ltr\">for</code> مقارنة، فيصبح كل عنصر قيمة منطقية."},{"text":"<code dir=\"ltr\">[65.0, 72.0]</code>","why":"هذا شكل التصفية، <code dir=\"ltr\">[t for t in totals if t &gt; 50]</code>، حيث يأتي الشرط بعد الـ <code dir=\"ltr\">for</code>."},{"text":"<code dir=\"ltr\">2</code>","why":"العدّ يحتاج <code dir=\"ltr\">sum(t &gt; 50 for t in totals)</code>؛ والـ list comprehension تبني قائمة دائمًا."},{"text":"خطأ <code dir=\"ltr\">SyntaxError</code>","why":"أيّ تعبير يمكن أن يأتي قبل <code dir=\"ltr\">for</code>، ومنه المقارنة."}],"answer":0}],"s-pda-2":[{"q":"<p>بعد <code dir=\"ltr\">orders = pd.read_csv(&quot;orders.csv&quot;)</code>، يُطلق <code dir=\"ltr\">orders[&quot;order_date&quot;].dt.month</code> الخطأ <code dir=\"ltr\">AttributeError: Can only use .dt accessor with datetimelike values</code>. ما الإصلاح؟</p>","options":[{"text":"استخدم <code dir=\"ltr\">orders[&quot;order_date&quot;].month</code> بدلًا من ذلك.","why":"أجزاء التاريخ في العمود تمرّ دائمًا عبر <code dir=\"ltr\">.dt</code>؛ وبدونها تحصل على <code dir=\"ltr\">AttributeError</code> آخر."},{"text":"رتّب العمود أولًا.","why":"ترتيب التواريخ النصية لا يغيّر نوعها."},{"text":"حمّل الملف مع <code dir=\"ltr\">parse_dates=[&quot;order_date&quot;]</code> (أو حوّل بـ <code dir=\"ltr\">pd.to_datetime</code>) كي يصبح العمود <code dir=\"ltr\">datetime64</code>.","why":"صحيح. قُرئ العمود نصًا (<code dir=\"ltr\">object</code>)، و<code dir=\"ltr\">.dt</code> لا تعمل إلا على أعمدة التواريخ."},{"text":"احذف الصفوف التي تواريخها مفقودة.","why":"لا توجد تواريخ مفقودة؛ المشكلة في نوع العمود."}],"answer":2},{"q":"<p>ماذا تعيد <code dir=\"ltr\">products.loc[products[&quot;unit_price&quot;] &gt; 100, &quot;name&quot;]</code>؟</p>","options":[{"text":"DataFrame بكل الأعمدة للمنتجات التي يتجاوز سعرها 100 دولار","why":"تسمية عمود واحد بعد الفاصلة تعيد ذلك العمود فقط."},{"text":"Series بأسماء المنتجات التي يتجاوز سعرها 100، مفهرسة بتسميات صفوفها","why":"صحيح. القناع يختار الصفوف و<code dir=\"ltr\">&quot;name&quot;</code> يختار عمودًا واحدًا، فتكون النتيجة Series."},{"text":"<code dir=\"ltr\">True</code> أو <code dir=\"ltr\">False</code> لكل منتج","why":"هذا هو القناع نفسه، <code dir=\"ltr\">products[&quot;unit_price&quot;] &gt; 100</code>، قبل استخدامه في الاختيار."},{"text":"عدد المنتجات التي يتجاوز سعرها 100","why":"العدّ يحتاج <code dir=\"ltr\">.sum()</code> على القناع أو <code dir=\"ltr\">len()</code> على النتيجة."}],"answer":1},{"q":"<p>أيّ سطر يرفع سعر المنتجات النشطة بنسبة 5% ويحدّث <code dir=\"ltr\">products</code> نفسه بشكل موثوق؟</p>","options":[{"text":"<code dir=\"ltr\">products[products[&quot;is_active&quot;] == 1][&quot;unit_price&quot;] *= 1.05</code>","why":"إسناد متسلسل: التصفية تنشئ جدولًا جديدًا، والتغيير يُطبَّق على تلك النسخة فقط."},{"text":"<code dir=\"ltr\">products[&quot;unit_price&quot;][products[&quot;is_active&quot;] == 1] *= 1.05</code>","why":"متسلسل أيضًا؛ ومع Copy-on-Write لا يصل أبدًا إلى <code dir=\"ltr\">products</code>."},{"text":"<code dir=\"ltr\">products.unit_price * 1.05</code>","why":"هذا يحسب أسعارًا جديدة لكل منتج ثم يرمي النتيجة."},{"text":"<code dir=\"ltr\">products.loc[products[&quot;is_active&quot;] == 1, &quot;unit_price&quot;] *= 1.05</code>","why":"صحيح. استدعاء واحد لـ <code dir=\"ltr\">.loc</code> يسمّي الصفوف والعمود، فيحدث الإسناد على <code dir=\"ltr\">products</code>."}],"answer":3},{"q":"<p>ما نتيجة <code dir=\"ltr\">s1 + s2</code>؟</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn\" data-action=\"copy\" aria-label=\"نسخ الكود\"><svg class=\"icon \" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\" aria-hidden=\"true\" focusable=\"false\"><rect width=\"14\" height=\"14\" x=\"8\" y=\"8\" rx=\"2\" ry=\"2\"/><path d=\"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2\"/></svg><span>نسخ</span></button></span></div><pre class=\"shiki\" tabindex=\"0\"><code><span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">s1 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.Series([</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">10</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">20</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </span><span style=\"color:#953800;--shiki-dark:#FFA657\">index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"a\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"b\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">s2 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.Series([</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </span><span style=\"color:#953800;--shiki-dark:#FFA657\">index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"b\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"c\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span></code></pre></div>\n","options":[{"text":"<code dir=\"ltr\">a: NaN, b: 21, c: NaN</code>","why":"صحيح. تُطابَق القيم بحسب التسمية؛ وحدها <code dir=\"ltr\">b</code> موجودة في الطرفين، والتسميات الموجودة في طرف واحد تعطي <code dir=\"ltr\">NaN</code>."},{"text":"<code dir=\"ltr\">a: 11, b: 22</code>","why":"هذا جمع بحسب الموقع، ولا تفعله pandas مع Series لها تسميات مختلفة."},{"text":"<code dir=\"ltr\">a: 10, b: 21, c: 2</code>","why":"النظائر المفقودة لا تُعامَل كأصفار؛ استخدم <code dir=\"ltr\">s1.add(s2, fill_value=0)</code> لهذا السلوك."},{"text":"خطأ <code dir=\"ltr\">ValueError</code> لأن الفهرسين مختلفان","why":"تحاذي pandas الفهارس المختلفة بدلًا من إطلاق خطأ."}],"answer":0},{"q":"<p>تريد كل الطلبات التي جاءت من الويب أو من تطبيق الهاتف. أيّ تصفية هي الخيار الصحيح الأوضح؟</p>","options":[{"text":"<code dir=\"ltr\">orders[orders[&quot;channel&quot;] == &quot;web&quot; or orders[&quot;channel&quot;] == &quot;mobile_app&quot;]</code>","why":"الكلمة <code dir=\"ltr\">or</code> تحتاج True/False واحدة، فتُطلق pandas الخطأ <code dir=\"ltr\">ValueError: The truth value of a Series is ambiguous</code>."},{"text":"<code dir=\"ltr\">orders[orders[&quot;channel&quot;] == [&quot;web&quot;, &quot;mobile_app&quot;]]</code>","why":"مقارنة عمود بقائمة تجري مقارنة عنصرًا بعنصر مع قائمة بطول مختلف، وهذا يُطلق خطأً."},{"text":"<code dir=\"ltr\">orders[orders[&quot;channel&quot;].isin([&quot;web&quot;, &quot;mobile_app&quot;])]</code>","why":"صحيح. تفحص <code dir=\"ltr\">isin</code> كل قيمة مقابل القائمة، وتُقرأ تمامًا مثل السؤال."},{"text":"<code dir=\"ltr\">orders.loc[&quot;web&quot;:&quot;mobile_app&quot;]</code>","why":"هذا يقطّع تسميات الصفوف، لا قيم القنوات؛ والفهرس هنا رقم الصف."}],"answer":2}],"s-pda-3":[{"q":"<p>يُحمَّل عمود كمية على هيئة <code dir=\"ltr\">float64</code> ويعرض قيمًا مثل <code dir=\"ltr\">1.0</code> و<code dir=\"ltr\">2.0</code>. ما التفسير، وما الذي يُبقي العمود أعدادًا صحيحة؟</p>","options":[{"text":"بعض الكميات كسور؛ قرّبها بـ <code dir=\"ltr\">round()</code>.","why":"الكميات هنا أعداد صحيحة؛ النوع يأتي من الخانات الفارغة لا من الكسور."},{"text":"بعض الخلايا فارغة، و<code dir=\"ltr\">NaN</code> الكلاسيكية عدد عشري، و<code dir=\"ltr\">astype(&quot;Int64&quot;)</code> تحتفظ بالأعداد الصحيحة مع <code dir=\"ltr\">&lt;NA&gt;</code> للفجوات.","why":"صحيح. النوع <code dir=\"ltr\">Int64</code> القابل للقيم المفقودة صُنع لهذه الحالة بالضبط."},{"text":"تحمّل <code dir=\"ltr\">read_csv</code> الأرقام دائمًا كأعداد عشرية؛ استخدم <code dir=\"ltr\">astype(int)</code>.","why":"الأعمدة التي بلا فجوات تُحمَّل على هيئة <code dir=\"ltr\">int64</code>؛ و<code dir=\"ltr\">astype(int)</code> تفشل ما دامت قيم <code dir=\"ltr\">NaN</code> موجودة."},{"text":"الملف تالف؛ أعِد تحميله مع <code dir=\"ltr\">keep_default_na=False</code>.","why":"هذا يُبقي الخانات الفارغة نصوصًا فارغة، فيتحوّل العمود كله إلى نص."}],"answer":1},{"q":"<p>أنتجت <code dir=\"ltr\">pd.to_numeric(cleaned, errors=&quot;coerce&quot;)</code> 12 قيمة <code dir=\"ltr\">NaN</code> جديدة. ماذا تفعل بعد ذلك؟</p>","options":[{"text":"استخدم <code dir=\"ltr\">fillna(0)</code> كي تكتمل المجاميع.","why":"هذا يحوّل 12 قيمة مجهولة إلى أصفار تبدو حقيقية، ويقلّل الإيراد عن حقيقته."},{"text":"احذف الصفوف الـ 12.","why":"قد تكون مبيعات حقيقية بصيغة غير متوقّعة؛ وحذفها يُضيع إيرادًا دون أن تعرف السبب."},{"text":"انتقل إلى <code dir=\"ltr\">astype(float)</code>، فهي أكثر صرامة.","why":"ستُطلق خطأً عند أول قيمة سيئة، وهذا يخبرك بأقل مما تخبرك به قائمة بكل القيم."},{"text":"اطبع النصوص الأصلية لتلك الصفوف ووسّع قاعدة التنظيف لكل صيغة تجدها.","why":"صحيح. الإجبار على التحويل وسيلة للعثور على القيم المشكلة، والنصوص الخام تخبرك بالقاعدة الناقصة."}],"answer":3},{"q":"<p>ماذا تعيد <code dir=\"ltr\">pd.to_datetime([&quot;03/04/2025&quot;, &quot;15/04/2025&quot;], format=&quot;%d/%m/%Y&quot;)</code>؟</p>","options":[{"text":"3 أبريل 2025 و15 أبريل 2025","why":"صحيح. الصيغة تقول إن اليوم أولًا، فتُحلَّل القيمتان، والصيغة الصريحة تزيل أي تخمين."},{"text":"4 مارس 2025 وخطأ","why":"هذه قراءة الشهر أولًا، <code dir=\"ltr\">%m/%d/%Y</code>، التي تفشل مع الشهر 15."},{"text":"4 مارس 2025 و15 أبريل 2025","why":"مع صيغة صريحة تُقرأ كل القيم بالطريقة نفسها؛ ولا تبدّل pandas بين قيمة وأخرى."},{"text":"قيمتا <code dir=\"ltr\">NaT</code>","why":"لا تظهر <code dir=\"ltr\">NaT</code> إلا مع <code dir=\"ltr\">errors=&quot;coerce&quot;</code> للقيم غير المطابقة؛ والقيمتان مطابقتان."}],"answer":0},{"q":"<p>دالة التنظيف لديك تحذف المكرّرات أولًا ثم تحذف المسافات من الأسماء بعد ذلك. ما الذي قد يسوء؟</p>","options":[{"text":"لا شيء؛ ترتيب الخطوات لا يهم.","why":"اكتشاف المكرّرات يقارن القيم مقارنة دقيقة، فالترتيب مهم."},{"text":"ستحذف <code dir=\"ltr\">strip()</code> حروفًا من الأسماء.","why":"لا تحذف <code dir=\"ltr\">strip()</code> إلا المسافات البيضاء في البداية والنهاية."},{"text":"النسخ التي لا تختلف إلا بالمسافات (<code dir=\"ltr\">&quot;Ali Evans&quot;</code> و<code dir=\"ltr\">&quot;Ali Evans &quot;</code>) لا تُعرَف كمكرّرات، فتنجو الاثنتان.","why":"صحيح. نظّف القيم أولًا، ثم ابحث عن المكرّرات."},{"text":"ستُطلق <code dir=\"ltr\">drop_duplicates</code> خطأً على الأعمدة النصية.","why":"إنها تعمل على أي نوع من الأعمدة."}],"answer":2},{"q":"<p>بعد <code dir=\"ltr\">df[&quot;country&quot;] = df[&quot;country&quot;].str.title()</code>، ما زالت <code dir=\"ltr\">nunique()</code> تعرض 9 دول بدلًا من 8. ما السبب الأرجح؟</p>","options":[{"text":"لا تعمل <code dir=\"ltr\">title()</code> مع الأحرف الكبيرة مثل <code dir=\"ltr\">EGYPT</code>.","why":"تعطي <code dir=\"ltr\">&quot;EGYPT&quot;.title()</code> القيمة <code dir=\"ltr\">&quot;Egypt&quot;</code>؛ فحالة الأحرف تُعالَج."},{"text":"بعض القيم فيها مسافات في البداية أو النهاية، فتبقى <code dir=\"ltr\">&quot;  Egypt&quot;</code> و<code dir=\"ltr\">&quot;Egypt&quot;</code> مختلفتين.","why":"صحيح. يجب أن تأتي <code dir=\"ltr\">str.strip()</code> قبل إصلاح حالة الأحرف (أو معه)."},{"text":"تعدّ <code dir=\"ltr\">nunique()</code> القيم المفقودة دولةً.","why":"تتجاهل <code dir=\"ltr\">nunique()</code> القيم المفقودة افتراضيًا."},{"text":"تحتفظ pandas بالقيم القديمة في الذاكرة المؤقتة حتى يُعاد تحميل الملف.","why":"الإسناد يستبدل العمود فورًا؛ ولا يُخزَّن شيء مؤقتًا."}],"answer":1}],"s-pda-4":[{"q":"<p>دمجت <code dir=\"ltr\">order_items</code> (3,991 صفًا) دمجًا أيسر مع <code dir=\"ltr\">returns</code> على <code dir=\"ltr\">order_item_id</code> مع <code dir=\"ltr\">indicator=True</code>. 198 صفًا قيمتها <code dir=\"ltr\">both</code>. ماذا تمثّل صفوف <code dir=\"ltr\">left_only</code>؟</p>","options":[{"text":"مرتجعات ليس لها بند طلب مطابق","why":"تلك ستكون <code dir=\"ltr\">right_only</code>، والربط الأيسر لا يحتفظ بها على أي حال."},{"text":"بنود طلبات أُرجعت مرتين","why":"البند المُرجَع مرتين سينتج صفّي <code dir=\"ltr\">both</code>، لا صف <code dir=\"ltr\">left_only</code>."},{"text":"صفوف فشل الدمج في معالجتها","why":"عمليات الدمج لا تفشل بصمت؛ و<code dir=\"ltr\">left_only</code> نتيجة طبيعية لها معنى."},{"text":"بنود الطلبات الـ 3,793 التي لم تُرجَع أبدًا","why":"صحيح. كل بند يبقى، والبنود التي ليس لها مرتجع مطابق تُعلَّم بـ <code dir=\"ltr\">left_only</code>."}],"answer":3},{"q":"<p>تعيد <code dir=\"ltr\">sales.pivot_table(index=&quot;channel&quot;, columns=&quot;year&quot;, values=&quot;revenue&quot;)</code> أرقامًا أصغر بكثير من مجاميع الإيراد. لماذا؟</p>","options":[{"text":"القيمة الافتراضية لـ <code dir=\"ltr\">aggfunc</code> هي <code dir=\"ltr\">&quot;mean&quot;</code>، فكل خلية هي متوسط إيراد البند، لا المجموع.","why":"صحيح. مرّر <code dir=\"ltr\">aggfunc=&quot;sum&quot;</code> للمجاميع؛ وحدّد دالة التجميع صراحةً دائمًا."},{"text":"تُسقط pivot_table الطلبات الملغاة تلقائيًا.","why":"لا تصفّي أبدًا بحسب الحالة؛ إنها تجمّع ما يُعطى لها فقط."},{"text":"القيم بآلاف الدولارات.","why":"لا تغيّر pandas مقياس القيم من تلقاء نفسها أبدًا."},{"text":"حُذفت الصفوف التي سنواتها مفقودة.","why":"حذف بضعة صفوف لا يمكن أن يقلّص كل خلية بهذا القدر، ولا توجد سنوات مفقودة."}],"answer":0},{"q":"<p>تُطلق <code dir=\"ltr\">orders.resample(&quot;ME&quot;)[&quot;revenue&quot;].sum()</code> الخطأ <code dir=\"ltr\">TypeError: Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex</code>. ما الإصلاح؟</p>","options":[{"text":"استخدم <code dir=\"ltr\">&quot;M&quot;</code> بدلًا من <code dir=\"ltr\">&quot;ME&quot;</code>.","why":"الاسم المستعار سليم؛ و<code dir=\"ltr\">&quot;M&quot;</code> هي الكتابة المُهمَلة وستصطدم بالخطأ نفسه."},{"text":"رتّب الطلبات بحسب التاريخ أولًا.","why":"الترتيب لا يمنح الجدول فهرسًا من نوع datetime."},{"text":"ضع التواريخ في الفهرس بـ <code dir=\"ltr\">set_index(&quot;order_date&quot;)</code>، أو مرّر <code dir=\"ltr\">on=&quot;order_date&quot;</code> إلى <code dir=\"ltr\">resample</code>.","why":"صحيح. تحتاج resample أن تعرف أيّ قيم التواريخ توزّعها على الحاويات."},{"text":"حوّل الإيراد إلى أعداد صحيحة.","why":"الخطأ يتعلّق بالفهرس، لا بالقيم التي تُجمع."}],"answer":2},{"q":"<p>يريد فريق البضائع تقسيم المنتجات بحسب السعر إلى خمس مجموعات في كل منها العدد نفسه من المنتجات. أيّ استدعاء يناسب؟</p>","options":[{"text":"<code dir=\"ltr\">pd.cut(products[&quot;unit_price&quot;], 5)</code>","why":"هذا يصنع خمسة نطاقات متساوية العرض؛ ومع وجود بضعة منتجات غالية، تقع معظم العناصر في المجموعة الأولى."},{"text":"<code dir=\"ltr\">pd.qcut(products[&quot;unit_price&quot;], 5)</code>","why":"صحيح. تقطع <code dir=\"ltr\">qcut</code> عند المئينات، فتحمل كل مجموعة نحو خُمس المنتجات."},{"text":"<code dir=\"ltr\">products[&quot;unit_price&quot;].rank(5)</code>","why":"تُرقّم <code dir=\"ltr\">rank</code> الصفوف؛ ووسيطها الأول ليس عدد مجموعات."},{"text":"<code dir=\"ltr\">products.groupby(&quot;unit_price&quot;).ngroups</code>","why":"هذا يعدّ الأسعار المختلفة؛ ولا يوزّع المنتجات على مجموعات."}],"answer":1},{"q":"<p>أيّ استدعاء يعيد الإيراد لكل دولة مع <code dir=\"ltr\">country</code> عمودًا عاديًا بدلًا من الفهرس؟</p>","options":[{"text":"<code dir=\"ltr\">sales.groupby(&quot;country&quot;)[&quot;revenue&quot;].sum()</code>","why":"هذا يعيد Series فهرسها الدولة."},{"text":"<code dir=\"ltr\">sales.groupby(&quot;country&quot;).sum(&quot;revenue&quot;)</code>","why":"هذا يجمع كل الأعمدة الرقمية ويبقى فهرسه الدولة."},{"text":"<code dir=\"ltr\">sales.pivot(index=&quot;country&quot;, values=&quot;revenue&quot;)</code>","why":"تحتاج <code dir=\"ltr\">pivot</code> الوسيط <code dir=\"ltr\">columns</code> ولا تجمّع أبدًا، لذا تفشل هنا، وكانت ستفشل أيضًا مع الدول المتكرّرة."},{"text":"<code dir=\"ltr\">sales.groupby(&quot;country&quot;, as_index=False)[&quot;revenue&quot;].sum()</code>","why":"صحيح. تُبقي <code dir=\"ltr\">as_index=False</code> مفتاح المجموعة عمودًا، جاهزًا للدمج أو التصدير."}],"answer":3}],"s-pda-5":[{"q":"<p>متوسط الصفحات المعروضة في جلسات الويب 4.2 والوسيط 3. يطلب مدير منتج الجلسة “النموذجية”. بماذا تجيب؟</p>","options":[{"text":"4.2 صفحة، لأن المتوسط يستخدم كل الجلسات","why":"بضع جلسات طويلة تسحب المتوسط إلى الأعلى، فلا يصف أي زائر نموذجي."},{"text":"متوسط الرقمين، 3.6 صفحة","why":"أخذ متوسط إحصاءين ينتج رقمًا بلا معنى."},{"text":"3 صفحات، أي الوسيط، ويُفضَّل مع نطاق مثل الرُّبيعين","why":"صحيح. في البيانات الملتوية يكون الوسيط هو القيمة النموذجية، والرُّبيعان يُظهران التشتّت."},{"text":"الحد الأقصى، لإظهار ما هو ممكن","why":"الحد الأقصى يصف جلسة متطرّفة واحدة، لا جلسة نموذجية."}],"answer":2},{"q":"<p>الارتباط بين <code dir=\"ltr\">added_to_cart</code> و<code dir=\"ltr\">purchased</code> عبر الجلسات يساوي 0.62. أيّ استنتاج سليم؟</p>","options":[{"text":"الجلسات التي تضيف إلى السلة أكثر احتمالًا بكثير أن تنتهي بشراء، وهذا يجعل السلة خطوة مفيدة للتتبّع في مسار الشراء.","why":"صحيح. يصف الارتباط علاقة قوية؛ والشراء يتطلّب عادةً سلة، فالنمط متوقّع."},{"text":"الإضافة إلى السلة تسبّب 62% من المشتريات.","why":"معامل الارتباط ليس نسبة من النتائج، ولا يقول شيئًا عن السبب وحده."},{"text":"62% من الجلسات تضيف إلى السلة.","why":"هذا سيكون متوسط <code dir=\"ltr\">added_to_cart</code>، وهو رقم مختلف."},{"text":"العمودان لا علاقة بينهما.","why":"0.62 تشير إلى علاقة موجبة قوية نسبيًا."}],"answer":0},{"q":"<p>من الشهر A إلى الشهر B: الإيراد زاد 20%، والطلبات زادت 20%، ومتوسط قيمة الطلب لم يتغيّر. ما الذي قاد النمو؟</p>","options":[{"text":"سلال أكبر","why":"متوسط قيمة الطلب لم يتغيّر، فلا يستطيع حجم السلة تفسير أي شيء هنا."},{"text":"أسعار أعلى","why":"الأسعار الأعلى كانت ستظهر في متوسط قيمة طلب أعلى، وقد بقي ثابتًا."},{"text":"لا يمكن تحديد ذلك دون بيانات العملاء.","why":"التفكيك يجيب عن ذلك على هذا المستوى أصلًا؛ وبيانات العملاء ستقسّمه أكثر."},{"text":"طلبات أكثر بالحجم المتوسط نفسه","why":"صحيح. الإيراد = الطلبات × متوسط قيمة الطلب، ولم يتحرّك إلا عدد الطلبات."}],"answer":3},{"q":"<p>تحتاج إلى عرض إيراد ثمانية أرباع كي يقارن مجلس الإدارة أحجامها. أيّ رسم بياني تختار؟</p>","options":[{"text":"رسم دائري من ثماني شرائح","why":"الرسوم الدائرية تخفي الترتيب الزمني، وتجعل ثماني شرائح متقاربة صعبة المقارنة."},{"text":"أعمدة رأسية بالترتيب الزمني، تبدأ من الصفر","why":"صحيح. الأعمدة تقارن المبالغ، والترتيب الزمني يُظهر الاتجاه، وخط الأساس عند الصفر يُبقي الأطوال صادقة."},{"text":"رسم خطي يبدأ محوره الرأسي من أصغر ربع","why":"التقريب يخفي حجم كل ربع؛ ولمقارنة المبالغ ابدأ من الصفر."},{"text":"مدرّج تكراري للإيراد الفصلي","why":"المدرّج التكراري يُظهر كيف تتوزّع القيم، ويُضيع أيّ ربع هو أيّ ربع."}],"answer":1},{"q":"<p>يتوقّف Restart and Run All بالخطأ <code dir=\"ltr\">NameError: name 'clean_orders' is not defined</code>، مع أن الـ notebook كان يعمل قبل ساعة. ما الذي حدث؟</p>","options":[{"text":"حُذفت الخلية التي تعرّف <code dir=\"ltr\">clean_orders</code> أو نُقلت تحت الخلية التي تستخدمها؛ وكانت الدالة موجودة فقط في الجلسة القديمة.","why":"صحيح. الحالة المخفية أخفت المشكلة؛ عرّف الدوال قبل استخدامها، أو استوردها من ملف <code dir=\"ltr\">.py</code>."},{"text":"رُقّيت pandas خلال تلك الساعة.","why":"الترقية لن تجعل اسم دالتك أنت غير معرَّف."},{"text":"أُعيدت تسمية ملف CSV.","why":"الملف المفقود يُطلق <code dir=\"ltr\">FileNotFoundError</code>، لا <code dir=\"ltr\">NameError</code>."},{"text":"لا يدعم Restart and Run All الدوال.","why":"إنه يشغّل كل الخلايا بالترتيب، ومنها تعريفات الدوال."}],"answer":0}]},"final":[{"q":"<p>ماذا تعيد <code dir=\"ltr\">sum(float(v.replace(&quot;,&quot;, &quot;&quot;)) for v in [&quot;1,234.50&quot;, &quot;99.00&quot;])</code>؟</p>","options":[{"text":"<code dir=\"ltr\">&quot;1,234.5099.00&quot;</code>","why":"تُحوَّل القيم إلى أعداد عشرية قبل الجمع، فلا تُلصق أي نصوص."},{"text":"خطأ <code dir=\"ltr\">ValueError</code>","why":"تُحذف الفواصل قبل أن ترى <code dir=\"ltr\">float()</code> النص، فينجح التحويلان."},{"text":"<code dir=\"ltr\">1333.5</code>","why":"صحيح. يُنظَّف كل نص ويُحوَّل، ثم تُجمع الأعداد العشرية."},{"text":"<code dir=\"ltr\">1234.5</code>","why":"الـ generator يغطي القيمتين، فتُضاف 99.0 أيضًا."}],"answer":2},{"q":"<p><code dir=\"ltr\">cancelled = orders[orders[&quot;status&quot;] == &quot;cancelled&quot;]</code> على طلبات Cartwheel. ما قيمة <code dir=\"ltr\">cancelled.shape</code>؟</p>","options":[{"text":"<code dir=\"ltr\">(2066, 7)</code>","why":"التصفية لا تحتفظ إلا بالصفوف المطابقة؛ أما الجدول الكامل ففيه 2,066."},{"text":"<code dir=\"ltr\">(105, 7)</code>","why":"صحيح. أُلغي 105 طلبات، وتصفية الصفوف تحتفظ بالأعمدة السبعة كلها."},{"text":"<code dir=\"ltr\">(105,)</code>","why":"هذا شكل Series؛ وتصفية DataFrame تعيد DataFrame."},{"text":"<code dir=\"ltr\">(7, 105)</code>","why":"الشكل دائمًا الصفوف أولًا ثم الأعمدة."}],"answer":1},{"q":"<p>تعيد <code dir=\"ltr\">messy[&quot;total&quot;].sum()</code> نصًا طويلًا بدلًا من رقم. أيّ خطوة أولى تشخّص المشكلة؟</p>","options":[{"text":"<code dir=\"ltr\">messy[&quot;total&quot;].round(2)</code>","why":"تقريب النص غير ممكن؛ فهو يُطلق <code dir=\"ltr\">TypeError</code> بدلًا من أن يفسّر شيئًا."},{"text":"<code dir=\"ltr\">messy.drop_duplicates()</code>","why":"المكرّرات تغيّر حجم المجموع، لا نوعه."},{"text":"<code dir=\"ltr\">messy[&quot;total&quot;].fillna(0)</code>","why":"ملء الخانات الفارغة لا يحوّل النص إلى أرقام."},{"text":"<code dir=\"ltr\">messy[&quot;total&quot;].dtype</code> ونظرة على بضع قيم، تكشفان نصًا مثل <code dir=\"ltr\">&quot;$65.00&quot;</code>","why":"صحيح. النوع <code dir=\"ltr\">object</code> في عمود أرقام يعني أن بعض القيم فيها حروف غير رقمية."}],"answer":3},{"q":"<p>يمكن لتذاكر الدعم أن تشير إلى طلب، ويمكن أن يكون للطلب الواحد عدة تذاكر. أيّ <code dir=\"ltr\">validate</code> تناسب <code dir=\"ltr\">orders.merge(tickets, on=&quot;order_id&quot;)</code>؟</p>","options":[{"text":"<code dir=\"ltr\">&quot;one_to_many&quot;</code>","why":"صحيح. كل معرّف طلب يظهر مرة واحدة في <code dir=\"ltr\">orders</code>، وربما عدة مرات في <code dir=\"ltr\">tickets</code>."},{"text":"<code dir=\"ltr\">&quot;many_to_one&quot;</code>","why":"هذه تؤكّد أن مفاتيح الطرف الأيمن فريدة؛ ومعرّفات الطلبات في التذاكر تتكرّر، فستُطلق <code dir=\"ltr\">MergeError</code>."},{"text":"<code dir=\"ltr\">&quot;one_to_one&quot;</code>","why":"معرّفات الطلبات في التذاكر تتكرّر، فهذه تُطلق خطأً."},{"text":"لا يمكن التحقّق لهذا الزوج من الجداول.","why":"التحقّق يعمل مع أيّ عملية دمج؛ وأنت تختار العلاقة التي تتوقّعها."}],"answer":0},{"q":"<p>تحتاج عدد الطلبات لكل عميل، لكن ليس بين يديك إلا <code dir=\"ltr\">order_items</code> (صف لكل بند). أيّ تجميع هو الصحيح؟</p>","options":[{"text":"<code dir=\"ltr\">items.groupby(&quot;customer_id&quot;).size()</code>","why":"ليس في <code dir=\"ltr\">order_items</code> عمود <code dir=\"ltr\">customer_id</code>، و<code dir=\"ltr\">size()</code> على البنود ستعدّ البنود لا الطلبات."},{"text":"<code dir=\"ltr\">items.groupby(&quot;order_id&quot;).size()</code>","why":"هذا يعدّ البنود لكل طلب، لا الطلبات لكل عميل."},{"text":"ادمج <code dir=\"ltr\">customer_id</code> من <code dir=\"ltr\">orders</code>، ثم <code dir=\"ltr\">groupby(&quot;customer_id&quot;)[&quot;order_id&quot;].nunique()</code>","why":"صحيح. معرّفات الطلبات المختلفة لكل عميل تعدّ الطلبات، أيًّا كان عدد بنود كل منها."},{"text":"<code dir=\"ltr\">items[&quot;order_id&quot;].value_counts()</code>","why":"هذا البنود لكل طلب مرة أخرى."}],"answer":2},{"q":"<p><code dir=\"ltr\">monthly</code> هي الإيراد لكل شهر في 2024 و2025. أيّ تعبير يقارن كل شهر بالشهر نفسه قبل سنة؟</p>","options":[{"text":"<code dir=\"ltr\">monthly.pct_change()</code>","why":"هذا يقارن كل شهر بالشهر الذي قبله، فيخلط معه الموسمية."},{"text":"<code dir=\"ltr\">monthly.pct_change(12)</code>","why":"صحيح. اثنتا عشرة فترة إلى الوراء هي الشهر نفسه في العام الماضي."},{"text":"<code dir=\"ltr\">monthly.rolling(12).mean()</code>","why":"المتوسط المتحرك ينعّم السلسلة؛ ولا يقارن الفترات."},{"text":"<code dir=\"ltr\">monthly.diff()</code>","why":"تعطي <code dir=\"ltr\">diff</code> التغيّرات من شهر إلى شهر بالدولار."}],"answer":1},{"q":"<p>ما التسمية التي تعطيها <code dir=\"ltr\">pd.cut([100], bins=[0, 100, 200])</code> للقيمة 100؟</p>","options":[{"text":"<code dir=\"ltr\">(100, 200]</code>","why":"الفئات مغلقة من اليمين افتراضيًا، فتنتمي 100 إلى الفئة التي تنتهي عند 100."},{"text":"<code dir=\"ltr\">NaN</code>","why":"تقع 100 داخل الحدود، فتحصل على تسمية."},{"text":"<code dir=\"ltr\">[100, 200)</code>","why":"فئة مغلقة من اليسار كهذه تحتاج <code dir=\"ltr\">right=False</code>؛ والقيمة الافتراضية تغلق الفئات من اليمين."},{"text":"<code dir=\"ltr\">(0, 100]</code>","why":"صحيح. مع القيمة الافتراضية <code dir=\"ltr\">right=True</code>، تشمل كل فئة حدّها الأيمن."}],"answer":3},{"q":"<p>أُضيف بالخطأ طلب واحد بقيمة 50,000 دولار إلى جدول من 2,000 طلب عادي. أيّ إحصاء بالكاد يتغيّر؟</p>","options":[{"text":"الوسيط","why":"صحيح. قيمة متطرّفة واحدة تحرّك الموقع الأوسط بصف واحد على الأكثر، فلا يكاد الوسيط يتحرّك."},{"text":"المتوسط","why":"يرتفع المتوسط بنحو 25 دولارًا، وهذا تحوّل كبير لطلب نموذجي قيمته بضع مئات."},{"text":"الانحراف المعياري","why":"قيمة متطرّفة واحدة تضخّم الانحراف المعياري كثيرًا."},{"text":"الحد الأقصى","why":"يقفز الحد الأقصى مباشرة إلى الطلب الخاطئ بقيمة 50,000 دولار."}],"answer":0},{"q":"<p>السطر <code dir=\"ltr\">q4 = orders[in_q4]</code> ثم <code dir=\"ltr\">q4[&quot;flag&quot;] = True</code>. ماذا يحدث لـ <code dir=\"ltr\">orders</code> مع Copy-on-Write؟</p>","options":[{"text":"يكتسب <code dir=\"ltr\">orders</code> عمودًا <code dir=\"ltr\">flag</code> قيمته <code dir=\"ltr\">True</code> لصفوف الربع الرابع.","why":"الجدول المُصفّى يتصرّف كنسخة؛ والتغييرات عليه لا ترجع أبدًا إلى الأصل."},{"text":"تُطلق pandas خطأً لأن <code dir=\"ltr\">q4</code> عرض (view).","why":"إسناد عمود جديد إلى <code dir=\"ltr\">q4</code> مسموح؛ لكنه يؤثّر في <code dir=\"ltr\">q4</code> وحده."},{"text":"لا شيء؛ وحده <code dir=\"ltr\">q4</code> يحصل على العمود الجديد.","why":"صحيح. لوضع علامة على صفوف داخل <code dir=\"ltr\">orders</code>، استخدم <code dir=\"ltr\">orders.loc[in_q4, &quot;flag&quot;] = True</code>."},{"text":"يحصل <code dir=\"ltr\">orders</code> على عمود <code dir=\"ltr\">flag</code> مملوء بـ <code dir=\"ltr\">True</code> لكل الصفوف.","why":"لا يُكتب شيء في <code dir=\"ltr\">orders</code> إطلاقًا."}],"answer":2},{"q":"<p>تعمل <code dir=\"ltr\">df[&quot;order_date&quot;].str.contains(&quot;2025&quot;)</code>، لكن <code dir=\"ltr\">df[&quot;order_date&quot;].dt.year</code> تفشل. ماذا يخبرك ذلك؟</p>","options":[{"text":"العمود يحمل تواريخ مع منطقة زمنية.","why":"أعمدة التواريخ تدعم <code dir=\"ltr\">.dt.year</code>، مع منطقة زمنية أو بدونها."},{"text":"العمود ما زال نصًا ويحتاج <code dir=\"ltr\">pd.to_datetime</code> قبل عمليات التاريخ.","why":"صحيح. عمل <code dir=\"ltr\">.str</code> وفشل <code dir=\"ltr\">.dt</code> هو بصمة التواريخ المخزّنة كنصوص."},{"text":"التواريخ ملتبسة.","why":"الالتباس يؤثّر في طريقة تحليل النص؛ ولا يمنع عمود تواريخ من استخدام <code dir=\"ltr\">.dt</code>."},{"text":"العمود فيه قيم مفقودة.","why":"القيم المفقودة تصبح <code dir=\"ltr\">NaT</code> في عمود التواريخ ولا تكسر <code dir=\"ltr\">.dt</code>."}],"answer":1},{"q":"<p>ارتفع إيراد ربع ما بنسبة 30%. وارتفع العملاء النشطون 30%؛ بينما بقيت الطلبات لكل عميل ومتوسط قيمة الطلب ثابتة. ما أفضل تلخيص؟</p>","options":[{"text":"أنفق العملاء أكثر في كل طلب.","why":"متوسط قيمة الطلب بقي ثابتًا."},{"text":"طلب العملاء بوتيرة أعلى.","why":"الطلبات لكل عميل بقيت ثابتة."},{"text":"ارتفعت الأسعار.","why":"ارتفاع الأسعار كان سيرفع متوسط قيمة الطلب، ولم يتغيّر."},{"text":"جاء النمو من وجود عملاء نشطين أكثر، يتصرّف كلٌّ منهم كما كان من قبل.","why":"صحيح. الإيراد = العملاء × الطلبات لكل عميل × متوسط قيمة الطلب، ولم يتحرّك إلا عدد العملاء."}],"answer":3},{"q":"<p>أيّ عادة تحمي أكثر من غيرها تقريرًا شهريًا متكرّرًا من الإبلاغ بصمت عن أرقام خاطئة حين تتغيّر صيغة ملف الشهر القادم؟</p>","options":[{"text":"دالة تنظيف تنتهي بـ assertions عن المعرّفات والتواريخ والمجاميع والقيم المسموح بها","why":"صحيح. حين تتغيّر الصيغة، يوقف assertion التشغيل برسالة بدلًا من ترك البيانات السيئة تصل إلى التقرير."},{"text":"تقريب كل رقم إلى دولارات صحيحة","why":"التقريب يخفي الفروق الصغيرة؛ ولا يكتشف مُدخلًا معطوبًا."},{"text":"تشغيل خلايا الـ notebook بترتيب مختلف كل شهر","why":"هذا يجعل النتائج أقل قابلية لإعادة الإنتاج، لا أكثر."},{"text":"استخدام <code dir=\"ltr\">errors=&quot;coerce&quot;</code> في كل مكان كي لا يتعطّل شيء","why":"الإجبار على التحويل دون فحوص يحوّل تغيّرات الصيغة إلى قيم <code dir=\"ltr\">NaN</code> صامتة، وهو بالضبط الفشل الذي تريد التقاطه."}],"answer":0}],"glossary":[{"id":"variable","term":"المتغيّر (variable)","definition":"اسم يُربط بقيمة باستخدام <code dir=\"ltr\">=</code>، مثل <code dir=\"ltr\">unit_price = 39</code>، كي يمكن استخدام القيمة لاحقًا؛ يُحسب الطرف الأيمن أولًا، ثم يشير الاسم إلى النتيجة.","lesson":"l-pda-1-2"},{"id":"dtype","term":"dtype","definition":"نوع البيانات المشترك بين كل القيم في عمود pandas، مثل <code dir=\"ltr\">int64</code> أو <code dir=\"ltr\">float64</code> أو <code dir=\"ltr\">object</code> (نص) أو <code dir=\"ltr\">bool</code> أو <code dir=\"ltr\">datetime64</code>؛ والنوع الخاطئ وراء كثير من أخطاء البيانات.","lesson":"l-pda-2-1"},{"id":"dictionary","term":"القاموس (dictionary)","definition":"حاوية في Python من أزواج المفتاح والقيمة، مثل اسم منتج مربوط بسعره؛ تبحث عن القيم بالمفتاح باستخدام <code dir=\"ltr\">d[key]</code> أو <code dir=\"ltr\">d.get(key, default)</code>.","lesson":"l-pda-1-3"},{"id":"list-comprehension","term":"List comprehension","definition":"طريقة لبناء قائمة في سطر واحد، <code dir=\"ltr\">[expr for x in items if condition]</code>، تطبّق تعبيرًا على كل عنصر، وتصفّي اختياريًا العناصر التي يُحتفظ بها.","lesson":"l-pda-1-4"},{"id":"f-string","term":"f-string","definition":"نص يسبقه الحرف <code dir=\"ltr\">f</code> ويضع القيم بين أقواس معقوفة مع تنسيق اختياري، مثل <code dir=\"ltr\">f&quot;{revenue:,.2f}&quot;</code> لتعطي 1,234.50 أو <code dir=\"ltr\">f&quot;{share:.1%}&quot;</code> لتعطي 12.5%.","lesson":"l-pda-1-5"},{"id":"traceback","term":"Traceback","definition":"التقرير الذي تطبعه Python حين يوقف استثناءٌ البرنامج؛ اقرأه من الأسفل، حيث يسمّي السطر الأخير نوع الخطأ ورسالته، ثم اصعد إلى السطر الذي فشل.","lesson":"l-pda-1-5"},{"id":"series","term":"Series","definition":"مصفوفة أحادية البعد من القيم في pandas مع فهرس من التسميات؛ والعمود الواحد في الـ DataFrame هو Series.","lesson":"l-pda-2-1"},{"id":"dataframe","term":"DataFrame","definition":"جدول pandas: أعمدة من نوع Series تتشارك فهرس صفوف واحدًا، مع methods لتحميل البيانات واختيارها وتصفيتها وتجميعها ودمجها وإعادة تشكيلها.","lesson":"l-pda-2-1"},{"id":"index-alignment","term":"محاذاة الفهرس (index alignment)","definition":"قاعدة pandas التي تجعل العمليات بين Series أو DataFrame وآخر تطابق القيم بحسب تسمية الفهرس لا بحسب الموقع؛ والتسميات الموجودة في طرف واحد فقط تنتج NaN.","lesson":"l-pda-2-1"},{"id":"loc-iloc","term":"loc و iloc","definition":"أداتا الاختيار الدقيقتان في pandas: <code dir=\"ltr\">.loc[rows, columns]</code> تختار بالتسمية وتشمل نهاية الشريحة، بينما <code dir=\"ltr\">.iloc</code> تختار بالموقع العددي وتستبعدها.","lesson":"l-pda-2-3"},{"id":"boolean-mask","term":"القناع المنطقي (boolean mask)","definition":"Series من قيم True و False، تأتي عادةً من مقارنة، وتُستخدم لاختيار الصفوف بـ <code dir=\"ltr\">df[mask]</code>؛ مجموعها يعدّ المطابقات ومتوسطها يعطي حصتها.","lesson":"l-pda-2-4"},{"id":"chained-assignment","term":"الإسناد المتسلسل (chained assignment)","definition":"الإسناد عبر عمليتي اختيار، مثل <code dir=\"ltr\">df[&quot;col&quot;][mask] = value</code>؛ قد يغيّر نسخة مؤقتة بدلًا من الـ DataFrame، فاستخدم بدلًا منه استدعاءً واحدًا لـ <code dir=\"ltr\">.loc</code>.","lesson":"l-pda-2-5"},{"id":"copy-on-write","term":"Copy-on-Write","definition":"سلوك في pandas، افتراضي منذ الإصدار 3.0 واختياري في 2.x، تتصرّف فيه كل عملية اختيار كنسخة، فتكون الطريقة الوحيدة لتغيير DataFrame هي الإسناد إليه مباشرة.","lesson":"l-pda-2-5"},{"id":"nan","term":"NaN","definition":"اختصار لعبارة “ليس رقمًا” (not a number): العلامة الكلاسيكية في pandas للقيمة المفقودة في الأعمدة العشرية؛ لا تساوي أي شيء، فافحص وجودها بـ <code dir=\"ltr\">isna()</code>.","lesson":"l-pda-3-1"},{"id":"nullable-dtype","term":"النوع القابل للقيم المفقودة (nullable dtype)","definition":"نوع في pandas مثل <code dir=\"ltr\">Int64</code> أو <code dir=\"ltr\">Float64</code> أو <code dir=\"ltr\">boolean</code> أو <code dir=\"ltr\">string</code> يخزّن القيم المفقودة على هيئة <code dir=\"ltr\">pd.NA</code>، فتبقى الأعمدة الصحيحة أعدادًا صحيحة حتى مع وجود فجوات.","lesson":"l-pda-3-1"},{"id":"str-accessor","term":"الـ accessor المسمّى str","definition":"الخاصية <code dir=\"ltr\">.str</code> في Series نصية، وتطبّق methods النصوص مثل <code dir=\"ltr\">strip</code> و<code dir=\"ltr\">title</code> و<code dir=\"ltr\">replace</code> و<code dir=\"ltr\">split</code> و<code dir=\"ltr\">contains</code> على كل القيم دفعة واحدة.","lesson":"l-pda-3-2"},{"id":"regular-expression","term":"التعبير النمطي (regular expression)","definition":"لغة أنماط للنصوص تحمل فيها حروف مثل <code dir=\"ltr\">$</code> و<code dir=\"ltr\">.</code> معاني خاصة؛ مرّر <code dir=\"ltr\">regex=False</code> لمعاملتها كحروف عادية.","lesson":"l-pda-3-3"},{"id":"ambiguous-date","term":"التاريخ الملتبس (ambiguous date)","definition":"نص تاريخ مثل 05/08/2025 يكون صالحًا وفق قراءة اليوم أولًا وقراءة الشهر أولًا معًا؛ ووحدها المعلومات الخارجية تحسم أيّهما الصحيح.","lesson":"l-pda-3-4"},{"id":"assertion","term":"Assertion","definition":"جملة <code dir=\"ltr\">assert condition, message</code> لا تفعل شيئًا حين يتحقّق الشرط، وتوقف البرنامج بالرسالة حين يفشل؛ تُستخدم لتحديد ما يجب أن تبدو عليه البيانات النظيفة.","lesson":"l-pda-3-5"},{"id":"groupby","term":"التجميع (groupby)","definition":"عملية pandas التي تقسم الصفوف إلى مجموعات بحسب مفتاح، وتطبّق حسابًا على كل مجموعة، وتضمّ النتائج في جدول واحد (split-apply-combine).","lesson":"l-pda-4-1"},{"id":"named-aggregation","term":"الحسابات التجميعية المسمّاة (named aggregation)","definition":"صيغة من <code dir=\"ltr\">agg</code> تسمّي فيها كل كلمة مفتاحية عمودًا ناتجًا، وقيمتها زوج (عمود، دالة)، مثل <code dir=\"ltr\">revenue=(&quot;revenue&quot;, &quot;sum&quot;)</code>.","lesson":"l-pda-4-1"},{"id":"merge","term":"الدمج (merge)","definition":"method في pandas تدمج جدولين جنبًا إلى جنب بمطابقة قيم المفتاح؛ و<code dir=\"ltr\">how</code> تحدّد نوع الربط، و<code dir=\"ltr\">validate</code> تتحقّق من علاقة المفاتيح المتوقّعة.","lesson":"l-pda-4-2"},{"id":"join-type","term":"نوع الربط (join type)","definition":"القاعدة الخاصة بالمفاتيح غير المطابقة في عملية الدمج: inner يحتفظ بالمفاتيح الموجودة في الطرفين، و left بكل صف أيسر، و right بكل صف أيمن، و outer بكل المفاتيح.","lesson":"l-pda-4-2"},{"id":"long-wide","term":"البيانات الطويلة والعريضة (long and wide)","definition":"شكلان للبيانات نفسها: الطويلة فيها صف لكل ملاحظة، والعريضة تنشر متغيّرًا واحدًا عبر الأعمدة؛ تنقل <code dir=\"ltr\">pivot_table</code> من الطويل إلى العريض، وتعيد <code dir=\"ltr\">melt</code> العكس.","lesson":"l-pda-4-3"},{"id":"resample","term":"resample","definition":"method في pandas تجمّع الصفوف ذات فهرس التواريخ في فترات منتظمة مثل الأيام أو الأسابيع (<code dir=\"ltr\">W</code>) أو نهايات الأشهر (<code dir=\"ltr\">ME</code>) أو نهايات الأرباع (<code dir=\"ltr\">QE</code>)، بما في ذلك الفترات الفارغة.","lesson":"l-pda-4-4"},{"id":"year-over-year","term":"النمو السنوي (year-over-year)","definition":"التغيّر مقارنةً بالفترة نفسها قبل سنة، مثل <code dir=\"ltr\">pct_change(4)</code> على البيانات الفصلية؛ وهو يزيل الأنماط الموسمية من المقارنة.","lesson":"l-pda-4-4"},{"id":"qcut","term":"qcut","definition":"دالة في pandas تقسم القيم إلى مجموعات متساوية الحجم تقريبًا عند المئينات، مثل الرُّبيعات، بخلاف <code dir=\"ltr\">cut</code> التي تستخدم حدودًا تختارها أنت.","lesson":"l-pda-4-5"},{"id":"median","term":"الوسيط (median)","definition":"القيمة الوسطى في عمود مرتّب، ونصف القيم أقل منها؛ وفي البيانات الملتوية مثل قيم الطلبات تصف القيمة النموذجية أفضل من المتوسط.","lesson":"l-pda-5-1"},{"id":"correlation","term":"الارتباط (correlation)","definition":"رقم بين ‎-1 و1 يقيس مدى قوة تحرّك عمودين رقميين معًا في نمط خطي؛ وهو يدلّ على علاقة مصاحبة، لا على سبب.","lesson":"l-pda-5-1"},{"id":"reproducible-analysis","term":"التحليل القابل لإعادة الإنتاج (reproducible analysis)","definition":"تحليل يستطيع أيّ شخص إعادة تشغيله من الملفات الخام، من الأعلى إلى الأسفل، دون خطوات يدوية، ويحصل على النتائج نفسها، باستخدام المُعامِلات والدوال والـ assertions.","lesson":"l-pda-5-4"}]}