{"id":"l-pda-4-5","courseId":"python-data-analysis","lang":"ar","kind":"lesson","summary":"رتّب العملاء بحسب الإنفاق، وقِس مدى تركّز الإيراد، وحوّل رقمًا متصلًا إلى شرائح باستخدام cut (حدود ثابتة) و qcut (مجموعات متساوية الحجم).","html":"<p>“مَن أفضل عملائنا؟” سؤال يطرحه كل فريق مبيعات أو تسويق، والإجابة الصادقة لها جزءان: قائمة مرتّبة، وكم يهم أعلى تلك القائمة. في Cartwheel الإجابة لافتة، وهي تشكّل طريقة قراءتك لكل رقم إيراد، ومنها قفزة الربع الرابع.</p>\n<h2 id=\"sec-1\" tabindex=\"-1\">صف لكل عميل</h2>\n<p>ابدأ بجدول على مستوى العميل: صف لكل عميل، مع الطلبات والإنفاق، مبني بالتجميع (groupby) من الدرس 4.1.</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"0\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"0\" 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\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><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\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pandas </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_items.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"orders.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">parse_dates</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_date\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"quantity\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"unit_price\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"discount\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.merge(items.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">as_index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sum(), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">on</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">validate</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"one_to_one\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders[orders[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"status\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">!=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"cancelled\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customer_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).agg(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">orders</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"count\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">spend</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"sum\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</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\">(cust), </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customers with a non-cancelled order\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].describe().round(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span></code></pre><div class=\"run-output\" data-run-output=\"0\" hidden></div></div>\n<p>503 عملاء. بلغ الوسيط 551 دولارًا، والمتوسط 888، والأعلى 5,370. حين يقع المتوسط فوق الوسيط بكثير، فهناك قيم كبيرة قليلة تسحبه إلى الأعلى؛ ويعود الدرس 5.1 إلى ما يعنيه ذلك عند الإبلاغ عن المتوسطات.</p>\n<h2 id=\"sec-2\" tabindex=\"-1\">الترتيب</h2>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"1\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"1\" 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\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><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\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pandas </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_items.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"orders.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">parse_dates</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_date\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"quantity\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"unit_price\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"discount\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.merge(items.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">as_index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sum(), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">on</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">validate</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"one_to_one\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders[orders[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"status\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">!=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"cancelled\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customer_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).agg(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">orders</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"count\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">spend</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"sum\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"rank\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].rank(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">ascending</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">method</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"min\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"percentile\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].rank(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">pct</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">True</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(cust.sort_values(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"rank\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).head(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">5</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).round(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">top20 </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cust.nlargest(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">int</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\">(cust) </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\"> 0.2</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</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\">(top20), </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customers =\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">round</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(top20[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sum() </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sum(), </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"of revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span></code></pre><div class=\"run-output\" data-run-output=\"1\" hidden></div></div>\n<p>تعطي <code dir=\"ltr\">rank</code> كل صف مرتبته، و1 لأعلى إنفاق بسبب <code dir=\"ltr\">ascending=False</code>. والتعادل هو حيث تختلف الطرق: <code dir=\"ltr\">&quot;min&quot;</code> تعطي العملاء المتعادلين المرتبة نفسها وتقفز فوق الأرقام التالية، مثل جدول الدوري، و<code dir=\"ltr\">&quot;dense&quot;</code> لا تقفز أبدًا، و<code dir=\"ltr\">&quot;first&quot;</code> تكسر التعادل بحسب ترتيب الصفوف، والقيمة الافتراضية <code dir=\"ltr\">&quot;average&quot;</code> تعطيهم متوسط المراتب. وتحوّل <code dir=\"ltr\">pct=True</code> المراتب إلى مئينات بين 0 و1، تصلح للمقارنة بين مجموعات مختلفة الأحجام.</p>\n<p>السطر الأخير هو رقم التركّز: أعلى 100 عميل، أي خُمس القاعدة، يحقّقون 55.5% من الإيراد. هذا أقل تطرّفًا من قاعدة 80/20 المعروفة في الكتب، لكنه ما زال يعني أن خسارة حفنة من العملاء الكبار ستؤلم أكثر من خسارة مئة عميل صغير.</p>\n<h3 id=\"sec-3\" tabindex=\"-1\">الترتيب داخل المجموعات</h3>\n<p>مديرو الدول يريدون أفضل عملائهم هم، لا قائمة عالمية تزاحم فيها الأسواق الكبرى الجميع. تعمل <code dir=\"ltr\">rank</code> على عمود مجمَّع أيضًا، فتبدأ من 1 من جديد داخل كل مجموعة:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"2\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"2\" 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\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><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\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pandas </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_items.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"orders.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">parse_dates</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_date\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">customers </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customers.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"quantity\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"unit_price\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"discount\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.merge(items.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">as_index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sum(), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">on</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">validate</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"one_to_one\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders[orders[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"status\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">!=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"cancelled\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customer_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">as_index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).agg(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">spend</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"sum\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cust.merge(customers[[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customer_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"country\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]], </span><span style=\"color:#953800;--shiki-dark:#FFA657\">on</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customer_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">validate</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"one_to_one\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"rank_in_country\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cust.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"country\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].rank(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">ascending</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">method</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"first\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(cust[cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"rank_in_country\"</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 style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sort_values(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">ascending</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).round(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span></code></pre><div class=\"run-output\" data-run-output=\"2\" hidden></div></div>\n<p>التصفية على <code dir=\"ltr\">rank_in_country == 1</code> تحتفظ بأعلى منفق في كل دولة، ثمانية صفوف إجمالًا؛ والاحتفاظ بالمراتب 3 أو أقل سيعطي قائمة أعلى ثلاثة لكل دولة. تضمن <code dir=\"ltr\">method=&quot;first&quot;</code> صفًا واحدًا بالضبط لكل مرتبة حتى حين يتعادل عميلان، وهذا ما تريده لقائمة ثابتة الطول. ونمط “رتّب داخل المجموعة ثم صفِّ” هذا يجيب عن عائلة كاملة من الأسئلة: المنتج الأكثر مبيعًا في كل فئة، وأول طلب لكل عميل، وآخر تذكرة لكل طلب.</p>\n<h2 id=\"sec-4\" tabindex=\"-1\">cut: فئات بحدود تختارها أنت</h2>\n<p>يريد التسويق نطاقات إنفاق يستطيع تسميتها في حملة. أنت تختار الحدود:</p>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"3\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"3\" 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\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><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\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> numpy </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> np</span></span>\n<span class=\"line\"><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pandas </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_items.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"orders.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">parse_dates</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_date\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"quantity\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"unit_price\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"discount\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.merge(items.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">as_index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sum(), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">on</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">validate</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"one_to_one\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders[orders[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"status\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">!=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"cancelled\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customer_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).agg(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">orders</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"count\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">spend</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"sum\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"band\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.cut(cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </span><span style=\"color:#953800;--shiki-dark:#FFA657\">bins</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</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:#0550AE;--shiki-dark:#79C0FF\">250</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">500</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1000</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">2000</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, np.inf],</span></span>\n<span class=\"line\"><span style=\"color:#953800;--shiki-dark:#FFA657\">                      labels</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"&#x3C;250\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"250-500\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"500-1k\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"1k-2k\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"2k+\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(cust.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"band\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">observed</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">True</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].agg([</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"count\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"sum\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]).round(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">0</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span></code></pre><div class=\"run-output\" data-run-output=\"3\" hidden></div></div>\n<p>كل زوج من الحدود يعرّف فئة، مغلقة من اليمين افتراضيًا: <code dir=\"ltr\">(250, 500]</code> تشمل 500 ولا تشمل 250. والعملاء الـ 57 في النطاق <code dir=\"ltr\">2k+</code>، أي 11% من القاعدة، جلبوا 173,407 دولارات، أكثر من أي نطاق آخر. تعيد <code dir=\"ltr\">cut</code> عمودًا <strong>فئويًا (categorical)</strong> تحافظ فئاته على ترتيبك، فيسرد الجدول النطاقات من الأصغر إلى الأكبر لا أبجديًا.</p>\n<aside class=\"callout callout-mistake\" role=\"note\"><p class=\"callout-title\"><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\"><path d=\"m21.73 18-8-14a2 2 0 0 0-3.48 0l-8 14A2 2 0 0 0 4 21h16a2 2 0 0 0 1.73-3\"/><path d=\"M12 9v4\"/><path d=\"M12 17h.01\"/></svg><span><span class=\"callout-kind\">خطأ شائع</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>نسيان الحدود الخارجية</span></p>\n<p>الحدود <code dir=\"ltr\">[0, 250, 500, 1000]</code> تترك بصمت كل عميل فوق 1,000 بقيمة <code dir=\"ltr\">NaN</code>، والحد الأيسر يستبعد 0 نفسه. اختم القائمة بـ <code dir=\"ltr\">np.inf</code> (وابدأها تحت أدنى قيمة لديك، أو مرّر <code dir=\"ltr\">include_lowest=True</code>)، ثم تأكّد بـ <code dir=\"ltr\">band.isna().sum() == 0</code>.</p>\n</aside>\n<h2 id=\"sec-5\" tabindex=\"-1\">qcut: مجموعات متساوية الحجم</h2>\n<p>حين تريد مجموعات متساوية الحجم بدلًا من حدود ثابتة، تقطع <code dir=\"ltr\">qcut</code> عند المئينات (quantiles):</p>\n<figure class=\"diagram\"><svg class=\"diagram-svg\" focusable=\"false\" viewBox=\"0 0 700 200\" role=\"img\" aria-labelledby=\"l-pda-4-5-t1\"><defs><marker id=\"arrow-l-pda-4-5-1\" viewBox=\"0 0 10 10\" refX=\"9\" refY=\"5\" markerWidth=\"7\" markerHeight=\"7\" orient=\"auto-start-reverse\"><path d=\"M0 0 L10 5 L0 10 z\" class=\"d-arrowhead\"/></marker></defs>\n  <title id=\"l-pda-4-5-t1\">الصف العلوي: تقسم cut محور الإنفاق عند القيم الثابتة 250 و 500 و 1000 و 2000؛ والفئات تحمل أعدادًا مختلفة من العملاء. الصف السفلي: تقسم qcut عند الرُّبيعات 210 و 551 و 1236، فتحمل كل فئة من الفئات الأربع نحو 126 عميلًا.</title>\n  <text class=\"d-label-strong\" x=\"20\" y=\"40\">cut</text>\n  <rect class=\"d-box-accent\" x=\"80\" y=\"20\" width=\"120\" height=\"36\" rx=\"4\"/><text class=\"d-label\" x=\"140\" y=\"43\" text-anchor=\"middle\">143</text>\n  <rect class=\"d-box-accent\" x=\"205\" y=\"20\" width=\"80\" height=\"36\" rx=\"4\"/><text class=\"d-label\" x=\"245\" y=\"43\" text-anchor=\"middle\">92</text>\n  <rect class=\"d-box-accent\" x=\"290\" y=\"20\" width=\"110\" height=\"36\" rx=\"4\"/><text class=\"d-label\" x=\"345\" y=\"43\" text-anchor=\"middle\">118</text>\n  <rect class=\"d-box-accent\" x=\"405\" y=\"20\" width=\"90\" height=\"36\" rx=\"4\"/><text class=\"d-label\" x=\"450\" y=\"43\" text-anchor=\"middle\">93</text>\n  <rect class=\"d-box-accent\" x=\"500\" y=\"20\" width=\"60\" height=\"36\" rx=\"4\"/><text class=\"d-label\" x=\"530\" y=\"43\" text-anchor=\"middle\">57</text>\n  <text class=\"d-label-muted\" x=\"590\" y=\"43\">عميلًا</text>\n  <text class=\"d-label-strong\" x=\"20\" y=\"130\">qcut</text>\n  <rect class=\"d-box-success\" x=\"80\" y=\"110\" width=\"118\" height=\"36\" rx=\"4\"/><text class=\"d-label\" x=\"139\" y=\"133\" text-anchor=\"middle\">126</text>\n  <rect class=\"d-box-success\" x=\"203\" y=\"110\" width=\"118\" height=\"36\" rx=\"4\"/><text class=\"d-label\" x=\"262\" y=\"133\" text-anchor=\"middle\">126</text>\n  <rect class=\"d-box-success\" x=\"326\" y=\"110\" width=\"118\" height=\"36\" rx=\"4\"/><text class=\"d-label\" x=\"385\" y=\"133\" text-anchor=\"middle\">125</text>\n  <rect class=\"d-box-success\" x=\"449\" y=\"110\" width=\"118\" height=\"36\" rx=\"4\"/><text class=\"d-label\" x=\"508\" y=\"133\" text-anchor=\"middle\">126</text>\n  <text class=\"d-code\" x=\"200\" y=\"172\" text-anchor=\"middle\">210</text>\n  <text class=\"d-code\" x=\"323\" y=\"172\" text-anchor=\"middle\">551</text>\n  <text class=\"d-code\" x=\"446\" y=\"172\" text-anchor=\"middle\">1236</text>\n  <text class=\"d-label-muted\" x=\"600\" y=\"172\">حدود الرُّبيعات</text>\n</svg><figcaption>تستخدم cut حدودًا ثابتة؛ وتستخدم qcut أعدادًا متساوية</figcaption></figure>\n<div class=\"code-block\" dir=\"ltr\" data-lang=\"python\" data-run=\"python\" data-index=\"4\"><div class=\"code-head\"><span class=\"code-title\">Python</span><span class=\"code-actions\"><button type=\"button\" class=\"code-btn code-run\" data-action=\"run\" data-lang=\"python\" data-index=\"4\" 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\"><path d=\"M5 5a2 2 0 0 1 3.008-1.728l11.997 6.998a2 2 0 0 1 .003 3.458l-12 7A2 2 0 0 1 5 19z\"/></svg><span>تشغيل</span></button><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\">import</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pandas </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">as</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_items.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.read_csv(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"orders.csv\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">parse_dates</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_date\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"quantity\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"unit_price\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">*</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> (</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">1</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\"> -</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> items[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"discount\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.merge(items.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">as_index</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">False</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sum(), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">on</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">validate</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"one_to_one\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">orders </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders[orders[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"status\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">!=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\"> \"cancelled\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">]</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> orders.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"customer_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).agg(</span><span style=\"color:#953800;--shiki-dark:#FFA657\">orders</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"order_id\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"count\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">), </span><span style=\"color:#953800;--shiki-dark:#FFA657\">spend</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"revenue\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"sum\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span>\n<span class=\"line\"></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"quartile\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">] </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> pd.qcut(cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </span><span style=\"color:#953800;--shiki-dark:#FFA657\">q</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">4</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">labels</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Q1 low\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Q2\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Q3\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"Q4 high\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">])</span></span>\n<span class=\"line\"><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">share </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cust.groupby(</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"quartile\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">observed</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">True</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">)[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sum() </span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">/</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\"> cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"spend\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">].sum()</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(share.round(</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">3</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">))</span></span>\n<span class=\"line\"><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">print</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">(pd.qcut(cust[</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"orders\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">], </span><span style=\"color:#953800;--shiki-dark:#FFA657\">q</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0550AE;--shiki-dark:#79C0FF\">4</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">, </span><span style=\"color:#953800;--shiki-dark:#FFA657\">duplicates</span><span style=\"color:#CF222E;--shiki-dark:#FF7B72\">=</span><span style=\"color:#0A3069;--shiki-dark:#A5D6FF\">\"drop\"</span><span style=\"color:#1F2328;--shiki-dark:#E6EDF3\">).value_counts().sort_index())</span></span></code></pre><div class=\"run-output\" data-run-output=\"4\" hidden></div></div>\n<p>الرُّبيع الأعلى من العملاء يجلب 63.2% من الإيراد، والرُّبيع الأدنى 2.8%. ويبيّن السطر الأخير حدود <code dir=\"ltr\">qcut</code>: ثلث العملاء قدّموا طلبًا واحدًا بالضبط، فيكون أدنى حدّين للرُّبيعات كلاهما 1، وتُطلق <code dir=\"ltr\">qcut</code> العادية الخطأ <code dir=\"ltr\">ValueError: Bin edges must be unique</code>. تدمج <code dir=\"ltr\">duplicates=&quot;drop&quot;</code> الحدود المكرّرة، فتبقى مجموعات أقل وغير متساوية. وللأعداد التي فيها تعادلات كثيرة، تكون <code dir=\"ltr\">cut</code> مع حدود تختارها بيدك أوضح عادةً.</p>\n<aside class=\"callout callout-tip\" role=\"note\"><p class=\"callout-title\"><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\"><path d=\"M15 14c.2-1 .7-1.7 1.5-2.5 1-.9 1.5-2.2 1.5-3.5A6 6 0 0 0 6 8c0 1 .2 2.2 1.5 3.5.7.7 1.3 1.5 1.5 2.5\"/><path d=\"M9 18h6\"/><path d=\"M10 22h4\"/></svg><span><span class=\"callout-kind\">نصيحة</span><span class=\"callout-sep\" aria-hidden=\"true\"> · </span>سمِّ القاعدة لا الفئة فقط</span></p>\n<p>“Q4 high” تعني شيئًا مختلفًا في كل مرة تتغيّر فيها البيانات، لأن حدود الرُّبيعات تتحرّك. أما “أنفق أكثر من 1,236 دولارًا في 2024 و2025” فلا تتغيّر. حين تُستخدم شريحة خارج الـ notebook الخاص بك، اكتب حدودها. والأمر نفسه ينطبق على الفترة: نطاق العميل في جدول من سنتين ليس نطاقه في ربع واحد.</p>\n</aside>\n<p>في التمرين تقسّم العملاء إلى شرائح بنفسك. وبهذا تكتمل عُدّة التحليل؛ ويوجّهها القسم 5 نحو أسئلة حقيقية، بدءًا بما يستطيع المتوسط أن يخبرك به وما لا يستطيع.</p>\n","toc":[{"id":"sec-1","text":"صف لكل عميل","level":2},{"id":"sec-2","text":"الترتيب","level":2},{"id":"sec-3","text":"الترتيب داخل المجموعات","level":3},{"id":"sec-4","text":"cut: فئات بحدود تختارها أنت","level":2},{"id":"sec-5","text":"qcut: مجموعات متساوية الحجم","level":2}],"takeaways":["<code dir=\"ltr\">rank(ascending=False, method=&quot;min&quot;)</code> ترقّم الصفوف بحسب القيمة؛ و<code dir=\"ltr\">method</code> تحدّد طريقة ترقيم المتعادلين، و<code dir=\"ltr\">pct=True</code> تعطي ترتيبًا مئينيًا.","تضع <code dir=\"ltr\">pd.cut</code> القيم في فئات بحدود تختارها أنت؛ استخدم <code dir=\"ltr\">np.inf</code> حدًّا أخيرًا كي لا تقع أي قيمة خارجها.","تصنع <code dir=\"ltr\">pd.qcut</code> فئات فيها أعداد متساوية (تقريبًا) من الصفوف، مثل الرُّبيعات (quartiles)؛ وحين تتعادل قيم كثيرة، مرّر <code dir=\"ltr\">duplicates=&quot;drop&quot;</code>.","كلتاهما تعيد عمودًا فئويًا (categorical)، فجمّع بحسبه مع <code dir=\"ltr\">observed=True</code> ورتّب بحسب ترتيب الفئات لا أبجديًا.","رقم التركّز، مثل “أعلى 20% من العملاء يجلبون 55% من الإيراد”، كثيرًا ما يكون أنفع رقم مفرد تستطيع تقديمه للعمل."],"further":[{"title":"pandas.cut","url":"https://pandas.pydata.org/docs/reference/api/pandas.cut.html"},{"title":"pandas.qcut","url":"https://pandas.pydata.org/docs/reference/api/pandas.qcut.html"},{"title":"pandas.Series.rank","url":"https://pandas.pydata.org/docs/reference/api/pandas.Series.rank.html"}],"quiz":[{"q":"<p>تترك <code dir=\"ltr\">pd.cut(spend, bins=[0, 250, 500, 1000])</code> بعض العملاء بقيمة <code dir=\"ltr\">NaN</code>. مَن هم؟</p>","options":[{"text":"العملاء الذين أنفقوا 250 بالضبط","why":"مع القيمة الافتراضية <code dir=\"ltr\">right=True</code> تقع 250 في الفئة <code dir=\"ltr\">(0, 250]</code>، فتحصل على تسمية."},{"text":"العملاء الذين أنفقوا أكثر من 1,000","why":"صحيح. القيم التي تتجاوز الحد الأخير لا تنتمي إلى أي فئة. اختم الحدود بـ <code dir=\"ltr\">np.inf</code> لتلتقط كل شيء."},{"text":"العملاء الذين إنفاقهم صغير جدًا، مثل 18 دولارًا","why":"تقع 18 داخل <code dir=\"ltr\">(0, 250]</code>. وحده إنفاق قدره 0 بالضبط سيقع خارجها، لأن الحد الأيسر مستبعَد."},{"text":"العملاء الذين قدّموا طلبًا واحدًا فقط","why":"لا تنظر <code dir=\"ltr\">cut</code> إلا إلى القيم التي تمرّرها، وهي هنا الإنفاق؛ ولا دور لعدد الطلبات."}],"answer":1},{"q":"<p>تريد أربع مجموعات من العملاء في كل منها العدد نفسه من العملاء. أيّ أداة تناسب؟</p>","options":[{"text":"<code dir=\"ltr\">pd.cut(spend, 4)</code>","why":"الرقم الصحيح في <code dir=\"ltr\">bins</code> مع <code dir=\"ltr\">cut</code> يصنع أربعة نطاقات متساوية <strong>العرض</strong>، وهذا مع إنفاق ملتوٍ يضع معظم العملاء في الفئة الأولى."},{"text":"<code dir=\"ltr\">spend.rank(pct=True)</code>","why":"الترتيب المئيني خطوة في الاتجاه الصحيح، لكنه أرقام، لا أربع مجموعات مسمّاة."},{"text":"<code dir=\"ltr\">pd.qcut(spend, 4)</code>","why":"صحيح. تقطع <code dir=\"ltr\">qcut</code> عند الرُّبيعات، فتحمل كل مجموعة نحو ربع العملاء."}],"answer":2},{"q":"<p>يتعادل عميلان على المركز الثاني بحسب الإنفاق. مع <code dir=\"ltr\">rank(ascending=False, method=&quot;min&quot;)</code>، ما الترتيب الذي يحصلان عليه هما والعميل التالي؟</p>","options":[{"text":"2 و2 و4","why":"صحيح. تعطي <code dir=\"ltr\">min</code> الصفوف المتعادلة أدنى ترتيب في المجموعة، ويقفز الترتيب التالي ليأخذ التعادل في الحسبان، مثل ترتيب الفرق الرياضية."},{"text":"2 و3 و4","why":"هذا ما تفعله <code dir=\"ltr\">method=&quot;first&quot;</code>، التي تكسر التعادل بحسب ترتيب ظهور الصفوف."},{"text":"2 و2 و3","why":"هذا ما تفعله <code dir=\"ltr\">method=&quot;dense&quot;</code>، التي لا تترك فجوات بعد التعادل أبدًا."},{"text":"2.5 و2.5 و4","why":"هذا ما تفعله القيمة الافتراضية <code dir=\"ltr\">method=&quot;average&quot;</code>، التي تعطي الصفوف المتعادلة متوسط المراتب التي تشغلها."}],"answer":0}],"exercise":{"kind":"python","files":["order_items.csv","orders.csv"],"starter":"import numpy as np\nimport pandas as pd\n\nitems = pd.read_csv(\"order_items.csv\")\norders = pd.read_csv(\"orders.csv\", parse_dates=[\"order_date\"])\nitems[\"revenue\"] = items[\"quantity\"] * items[\"unit_price\"] * (1 - items[\"discount\"])\norders = orders.merge(items.groupby(\"order_id\", as_index=False)[\"revenue\"].sum(), on=\"order_id\", validate=\"one_to_one\")\norders = orders[orders[\"status\"] != \"cancelled\"]\n\n# 1. cust: one row per customer_id with columns orders (count) and spend (sum of revenue)\ncust = None\n\n# 2. Column \"rank\": 1 for the highest spender, ties share the lowest rank (\"min\")\n\n# 3. Column \"band\": spend bands with edges 0, 250, 500, 1000, 2000, infinity\n#    and labels \"<250\", \"250-500\", \"500-1k\", \"1k-2k\", \"2k+\"\n\n# 4. Share of all revenue from the top 10% of customers by spend (top 50), rounded to 3 decimals\ntop10_share = None\n","solution":"import numpy as np\nimport pandas as pd\n\nitems = pd.read_csv(\"order_items.csv\")\norders = pd.read_csv(\"orders.csv\", parse_dates=[\"order_date\"])\nitems[\"revenue\"] = items[\"quantity\"] * items[\"unit_price\"] * (1 - items[\"discount\"])\norders = orders.merge(items.groupby(\"order_id\", as_index=False)[\"revenue\"].sum(), on=\"order_id\", validate=\"one_to_one\")\norders = orders[orders[\"status\"] != \"cancelled\"]\n\ncust = orders.groupby(\"customer_id\").agg(orders=(\"order_id\", \"count\"), spend=(\"revenue\", \"sum\"))\n\ncust[\"rank\"] = cust[\"spend\"].rank(ascending=False, method=\"min\")\n\ncust[\"band\"] = pd.cut(cust[\"spend\"], bins=[0, 250, 500, 1000, 2000, np.inf],\n                      labels=[\"<250\", \"250-500\", \"500-1k\", \"1k-2k\", \"2k+\"])\n\ntop = cust.nlargest(50, \"spend\")\ntop10_share = round(top[\"spend\"].sum() / cust[\"spend\"].sum(), 3)\nprint(cust[\"band\"].value_counts().sort_index(), top10_share)\n","checks":[{"id":"cust","test":"isinstance(cust, pd.DataFrame) and len(cust) == 503 and {'orders', 'spend'} <= set(cust.columns)"},{"id":"rank","test":"'rank' in cust.columns and int(cust['rank'].min()) == 1 and int((cust.set_index('customer_id') if 'customer_id' in cust.columns else cust).loc[331, 'rank']) == 2"},{"id":"band","test":"'band' in cust.columns and int(cust['band'].isna().sum()) == 0 and cust['band'].astype(str).value_counts().to_dict() == {'<250': 143, '500-1k': 118, '1k-2k': 93, '250-500': 92, '2k+': 57}"},{"id":"top10","test":"round(float(top10_share), 3) == np.float64(0.355)"}],"title":"قسّم عملاء Cartwheel إلى شرائح","prompt":"<p>ابنِ <code dir=\"ltr\">cust</code>، صفًا لكل <code dir=\"ltr\">customer_id</code>، مع <code dir=\"ltr\">orders</code> (عدد الطلبات) و<code dir=\"ltr\">spend</code> (إجمالي الإيراد). أضِف <code dir=\"ltr\">rank</code> (1 لأعلى منفق، والمتعادلون يتشاركون أدنى مرتبة)، و<code dir=\"ltr\">band</code>، المصنوع بـ <code dir=\"ltr\">pd.cut</code> بالحدود 0 و250 و500 و1000 و2000 واللانهاية والتسميات <code dir=\"ltr\">&quot;&lt;250&quot;</code> و<code dir=\"ltr\">&quot;250-500&quot;</code> و<code dir=\"ltr\">&quot;500-1k&quot;</code> و<code dir=\"ltr\">&quot;1k-2k&quot;</code> و<code dir=\"ltr\">&quot;2k+&quot;</code>. وأخيرًا اجعل <code dir=\"ltr\">top10_share</code> حصة الإيراد الكلي التي تأتي من أعلى 50 عميلًا إنفاقًا (نحو أعلى 10%)، مقرّبة إلى 3 منازل عشرية.</p>\n","hints":["<code dir=\"ltr\">orders.groupby(&quot;customer_id&quot;).agg(orders=(&quot;order_id&quot;, &quot;count&quot;), spend=(&quot;revenue&quot;, &quot;sum&quot;))</code>.","<code dir=\"ltr\">cust[&quot;spend&quot;].rank(ascending=False, method=&quot;min&quot;)</code>؛ وللنطاقات، <code dir=\"ltr\">pd.cut(cust[&quot;spend&quot;], bins=[0, 250, 500, 1000, 2000, np.inf], labels=[...])</code>.","<code dir=\"ltr\">cust.nlargest(50, &quot;spend&quot;)[&quot;spend&quot;].sum()</code> مقسومًا على إجمالي الإنفاق، ثم <code dir=\"ltr\">round(..., 3)</code>."],"explanation":"<p>جدول العملاء تجميع (groupby) فوق الجدول الذي على مستوى الطلبات، فتكون الطلبات الملغاة مستبعدة أصلًا. لا تهم <code dir=\"ltr\">method=&quot;min&quot;</code> إلا مع التعادلات، وتجعل <code dir=\"ltr\">ascending=False</code> أكبر منفق في المرتبة 1 (العميل 36، بـ 5,370 دولارًا). إنهاء الفئات عند <code dir=\"ltr\">np.inf</code> لا يترك أي عميل بلا تسمية، وهذا ما يؤكّده الفحص. أعلى 50 عميلًا، أي عُشر القاعدة، يمثّلون 35.5% من الإيراد. أرقام التركّز هذه مكانها أي تقرير عن العملاء: فهي تخبرك هل تقلق بشأن الكثيرين أم القليلين.</p>\n","checkLabels":{"cust":"في <code dir=\"ltr\">cust</code> 503 عملاء مع الطلبات والإنفاق","rank":"يبدأ <code dir=\"ltr\">rank</code> من 1، والعميل 331 في المرتبة الثانية","band":"<code dir=\"ltr\">band</code> بلا فجوات وبالأعداد المتوقّعة لكل نطاق","top10":"<code dir=\"ltr\">top10_share</code> هي حصة أعلى 50 عميلًا من الإيراد"}},"words":588,"readMinutes":3}