diff --git a/polars_v_pandas/DataFrame_Plots.ipynb b/polars_v_pandas/DataFrame_Plots.ipynb new file mode 100644 index 0000000000..711c9201a4 --- /dev/null +++ b/polars_v_pandas/DataFrame_Plots.ipynb @@ -0,0 +1,207 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "8ced8243-d770-437e-a90d-f794ffa57fc0", + "metadata": {}, + "source": [ + "# Dataframe Plots\n", + "## (i) polars Plotting" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "1cf56fd3-605c-4449-8a5e-d0fd94b49080", + "metadata": {}, + "outputs": [], + "source": [ + "from data_generation import data_generation\n", + "\n", + "sales_data = data_generation(50)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "id": "014e9e56-8fff-45ab-85ff-eb51840f2bc7", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "\n", + "\n", + "
\n", + "" + ], + "text/plain": [ + "alt.Chart(...)" + ] + }, + "execution_count": 13, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "import polars as pl\n", + "\n", + "from data_generation import data_generation\n", + "\n", + "orders_polars = pl.DataFrame(sales_data)\n", + "\n", + "(\n", + " orders_polars.group_by(\"region\")\n", + " .agg(total_sales=pl.col(\"sales_income\").sum())\n", + " .plot.bar(x=\"region\", y=\"total_sales\")\n", + " .properties(width=200, height=200, title=\"Total Sales per Region ($)\")\n", + ")" + ] + }, + { + "cell_type": "markdown", + "id": "a62335eb-4763-4c46-adb2-d7386914f56b", + "metadata": {}, + "source": [ + "## (ii) Pandas Plotting" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "id": "85929590-e514-4497-b396-58cfe26e59d3", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAk0AAAHhCAYAAABzzIpQAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjMsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvZiW1igAAAAlwSFlzAAAPYQAAD2EBqD+naQAAO6NJREFUeJzt3Qm8zdX+//GPeZ6FRNGlzCpTmkUklcK9uCVJkzSgSOVSGkgZQ1IJRYZuSQpJUjdKSBmiuinKXObM9v/xXv/fd9+9z8A6p3Psc/Z5PR+Pb+fs7/6e715776P9Pmt91vpmC4VCIQMAAMAJZT/x3QAAABBCEwAAgAdCEwAAgAdCEwAAgAdCEwAAgAdCEwAAgAdCEwAAgAdCEwAAgAdCEwAAgAdCE4CwTz75xLJly+a+nmpXXHGF23DqjB8/3r3fP//8c0wef9++fVaqVCmbNGlSsu17/PHHk7zvyJEjVr58eRs9enQ6txL4H0ITEGP60PLZfILMM888YzNmzDgl7V65cqW1adPGzjrrLMubN6+dccYZdtVVV9kLL7xwSh4/XiR8nwsXLmyXX365vf/++xbvhg8fboUKFbJ27dql+Gdz5cplPXr0sKefftoOHjyYLu0DEsqZaA+AU+r111+Puj1x4kSbN29eov1Vq1b1Ck0KMjfccIOlp0WLFlmjRo3szDPPtDvuuMPKlCljGzdutC+++MJ9EN53333p+vjxRmHzlltuMV0K9JdffrEXX3zRrrvuOps9e7Y1a9Ys3R63Q4cOLrDkyZPHTjX1FOl3pXv37pYjR45kjzl8+LB7XRQoE+rUqZP17t3bJk+ebLfddtspaDWyOkITEGM333xz1G0FD4WmhPszEv11X6RIEfvqq6+saNGiUfdt27YtZu3KiNQLkjt3bsuePfmO/XPOOSfq/W7durVVq1bNhYr0DE0KK8kFlvQ2a9Ys2759u/3jH/9IdN+AAQNs2LBh4d+l559/3s477zwbMWKEXXjhheHj9LvXtGlTN4xHaMKpwPAckAns37/fHnzwQVfDoV6Bc889132Q6C/wgP4S13ETJkwID/Xceuut7j71Xtxzzz3u5/Lly2clSpSwv//976muZfnvf/9r1atXTxSYRDUqkV577TW78sor3X61XWFAPSk+Dh06ZP369bNKlSq5n9Xz79Wrl9sfSSHzkksuce0pWLCge56PPvroSc+v1+jee+91NTX6GQ0z1qlTxz799NNEx/7222/ug7l06dKuLXr+48aNS7ImbMqUKdanTx83ZJk/f37bs2ePpYR6FUuWLOle59S8HgcOHLD777/fnUPDX9dff71rv9oWWSOUXE2T6oT0/PQYZcuWta5du9quXbuijlH9WY0aNWzNmjWu11HPU8930KBBXs9Rw8gVKlSwv/3tb1H71Sa9d+p903No3769G/LVc1VvZkI67j//+Y/98ccfXo8L/BX0NAEZnIKRPvQWLFhgnTt3dn9xz50713r27Ok+CIcOHeqO03De7bffbvXr17c777zT7Qs+kNQjpCE1DcWUK1fOfUgquOiDTx96+sBLCdUxLV682FatWuU+OE9Ej6MPYD2HnDlz2nvvvecC3PHjx92HcXJ0v35GH4h6PgoSqqPS8/3+++/DtVurV6+2a6+91mrVqmX9+/d3H/Q//vijff75517PZeHChTZ16lT3Aa2fVWC4+uqrbcmSJeHntnXrVtfDEYSs0047zQ2d6f1QIOrWrVvUOZ988knXu/TQQw+5QKPvU2L37t22c+fOqEDh+3qIwvK0adPc8JvarefYokULr8dWqHriiSesSZMm1qVLF1u3bp17D/U7pNdUtUQBtVGvVatWrVyP0VtvvWUPP/yw1axZ05o3b37Cx9Hv4wUXXJBov2q51POm32f9AaDf1bvuusttSVHI1b8RnU+/B0C6CgHIULp27aruo/DtGTNmuNtPPfVU1HFt2rQJZcuWLfTjjz+G9xUoUCDUsWPHROf8888/E+1bvHixO+/EiRPD+xYsWOD26euJfPjhh6EcOXK4rWHDhqFevXqF5s6dGzp8+LDXYzdr1ix09tlnR+27/PLL3RZ4/fXXQ9mzZw999tlnUceNGTPGtfHzzz93t4cOHepub9++PZRS+jltS5cuDe/75ZdfQnnz5g3deOON4X2dO3cOnX766aEdO3ZE/Xy7du1CRYoUCT/H4PXTc0vqeSfXBp1f7d+2bZtry9VXX+32P/fccyl+PZYtW+Zud+vWLeq4W2+91e3v169feN9rr73m9q1fv97d1uPnzp071LRp09CxY8fCx40cOdIdN27cuPA+vVcJf38OHToUKlOmTKh169YnfM5Hjhxxv7sPPvhgovvatm0bOuuss9wxal9ke5OyadMm145nn332hMcBaYHhOSCD++CDD1zdiXpCImm4Tp+56vE4GQ3JRRbX/v77726IR8NZy5cvT3GbNCSinib1fHzzzTduSEa1NxqemTlzZrKPrR6UHTt2uNlhP/30k7udnOnTp7velCpVqrifCTYN9Yl63iQYInz33Xddb0xKNWzY0PVWBFTc3rJlS9ebd+zYMfca//vf/3aF2fo+si16znoOCV/Djh07Rj3vk3n11Vdd75WGMOvWrWvz5893w26aHZbS12POnDnuq3rzIvkU53/00Ueu8Fo9Z5E1WCr216y+hDP6NBQaWYulHjX1dOq9PRENpem1LFasWKL71Eum4eRLL73UPZ7qnvQ7m5zgHHotgPRGaAIyOH2AqK5EtSlJzabT/SejGpe+ffuGa6JU66IPadWpnCi4nEi9evXs7bffdkM0Gsp65JFHbO/evW72nob8AhrS0VBPgQIFXMDR4wb1Rid67B9++MENven4yE1DNxIUCbdt29YuvvhiNzSpeiMNQWpoyjdAVa5cOdE+Pcaff/7pPrC16XUaO3ZsorZo9lZkWwIVK1a0lFBIU12WQoKGxzQMqMePDC6+r4d+H/RzCdugkHwywe+S6rsiKQydffbZiX7XNNSbcFabQox+J3xE1uQFNNyn0KiQpmJxDZfqnBqeS6puKThHUrPrgLRGTROQBaiXQQXZ6kFQz4pmvulDRgEjNb0zCT9QFaC06QNcQUK9IipYViFz48aNXe/IkCFDXGjT8eo9Uy3OiR5b96k2Rj+XFJ1L1KOjwm31tCh0qKdFNUrqgfnwww//8uywoI3qUVEPUlJUTxUpJb1MQfhQsJRrrrnGhVrVTqnAWvVCKXk9TqXkXtukwlCk4sWLu9+/5MKV3jttKgrX+6oeTE18UGgLetICwTn0mgHpjdAEZHAqutawiXpxInub1q5dG74/kNxf2yrQ1Qf+4MGDo6bCJ5wR9VdpaEk2b97svqroW4XQGrLTsFcgGEo6ERVBa+hPoetkvQjqWdFx2hQqtF7VY4895h4nCCPJUQ9OQiqsVnG8enJEr7uG6k52rrSiXhWFSs3Au/HGG93z93099PuggLV+/fqoXjQVx59M8Luk4m/1LAU0ZKfzpdXz14QAPR+d82TUY6beN60ePnLkyET/DoJz+KxjBvxVDM8BGZx6HvSBrQ+MSPpQ1Ydn5CwlDYElFYTUI5Dwr39N49Z5U0NhJKneBPUgRQ7vBD0RkcdqSE69Xiej2ViaHfjyyy8nOdyo5RUkqSEbzTCUhFPxk6LarMiaJE1rV32U1v8J1jHSukmqa9JswYQ0fJfWFCpUs/bdd9+5tqTk9QjWdUp4eRGfldoVitQTqPWQIt8z1VzpffOdgedDPZ5Lly5NtD+53ifVNem9SDgTcdmyZe7fgc4HpDd6moAMTgXIGqZRz4mmX9euXdsNO+nDVMNtkdPSVdCsXin1tqgOSn+lN2jQwE3F1hRuDctpnSQFBR2n9ZpSO9ynmhv1gmjoTT0RmvKtYTGtvRPU+ih46ENOz0G9J+ot0Ie+Cp6D3qjkaLq8apPuvvtuF9JUt6SQpx427Vehtnq2tMyAhuf0ga6eEtX2KDBoyEtrN52MlhVQ0IhcckA07T4wcOBA1wa9liqK1muosKawpdcxPdYIUkG06tCeffZZt8K77+uh3wGFPC0OqYL/YMkB9Z7JiXqp1LOm2jQ9d9UWqdBfvU56TTT8mpYLrqqOS7+TaldQlxWEQ9Wm6XdW96knSctrvPLKK+55JVy9XLVgei1S+7sMpEiazMEDkG5LDsjevXtD3bt3D5UtWzaUK1euUOXKld109OPHj0cdt3bt2tBll10WypcvnztHsPzAzp07Q506dQqVLFkyVLBgQTflX8dqanfkEgW+Sw7Mnj07dNttt4WqVKnizqdp6pUqVQrdd999oa1bt0YdO3PmzFCtWrXcNP4KFSq4qeGauh451T2pJQdESxjo+OrVq4fy5MkTKlasWKhOnTqhJ554IrR79253zPz580MtW7Z0r43aoa/t27cPff/99yd9rdUGvd5vvPGGe031GOeff36Sz1/PS8eWL1/evQeaWt+4cePQ2LFjE71+06dPP+ljJ2xDUh5//PGo98Pn9ZD9+/e7cxYvXty9PzfccENo3bp17lwDBw5MdsmByCUG9N7qeZYuXTrUpUsX9zsUSe+V2pGQfp/0e3UyWp5Av49PPvlk1P6PPvoovOyAHj9nzpyhihUruuUJ9uzZE3Xsrl273Hv+yiuvnPTxgLSQTf9JWcwCgPigXhctsJlw6DMerVixws4//3x744037KabbrKMQIuAaqhWdWVJFZWrEFy9q5GrmEdSb5qWu9CEg5QW3wOpQU0TAMQZ1TglFTBUMH/ZZZdZRqGL9WrIVpedSSnVOGkYWsXyBCacKtQ0AUCcUe+LCqRVC6eici2Aqk2XX4nF0gTJ0eKYJ7rAswr6VSOXFF3OZcOGDenYOiAxQhMAxJmLLrrIFUhr+Es9OVruQUNcmkyQmQSzIIGMgpomAAAAD9Q0AQAAeCA0AQAAeKCmKY3osgWbNm1yy/tz4UgAADIHVSnp8jxaEDjyItlJITSlEQWmjDQrBQAA+NMllHQlgRMhNKWR4AKSetELFy4c6+YAAAAPe/bscZ0ekReCTg6hKY0EQ3IKTIQmAAAyF5/SGgrBAQAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPBCaAAAAPOT0OQgAAJwaFXq/b1nRzwNbWEZHTxMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAIAHQhMAAEBmC00DBw60bNmyWbdu3cL7Dh48aF27drUSJUpYwYIFrXXr1rZ169aon9uwYYO1aNHC8ufPb6VKlbKePXva0aNHo4755JNP7IILLrA8efJYpUqVbPz48Ykef9SoUVahQgXLmzevNWjQwJYsWZKOzxYAAGQmGSY0ffXVV/bSSy9ZrVq1ovZ3797d3nvvPZs+fbotXLjQNm3aZK1atQrff+zYMReYDh8+bIsWLbIJEya4QNS3b9/wMevXr3fHNGrUyFasWOFC2e23325z584NHzN16lTr0aOH9evXz5YvX261a9e2Zs2a2bZt207RKwAAADKybKFQKBTrRuzbt8/1Ao0ePdqeeuopO++882zYsGG2e/duO+2002zy5MnWpk0bd+zatWutatWqtnjxYrvwwgtt9uzZdu2117owVbp0aXfMmDFj7OGHH7bt27db7ty53ffvv/++rVq1KvyY7dq1s127dtmcOXPcbfUs1atXz0aOHOluHz9+3MqXL2/33Xef9e7d+6TPYc+ePVakSBHX5sKFC6fTKwUAiHcVer9vWdHPA1vE5HFT8vmdIXqaNPymnqAmTZpE7V+2bJkdOXIkan+VKlXszDPPdKFJ9LVmzZrhwCTqIdKLsHr16vAxCc+tY4JzqJdKjxV5TPbs2d3t4JiEDh065B4jcgMAAPErZ6wbMGXKFDccpuG5hLZs2eJ6iooWLRq1XwFJ9wXHRAam4P7gvhMdo6Bz4MAB27lzpxvmS+oY9WwlZcCAAfbEE0+k6jkDAIDMJ6Y9TRs3brQHHnjAJk2a5IqvM5NHHnnEdeUFm54LAACIXzENTRoSU6G16ply5szpNhV7jxgxwn2vnh4Nnan2KJJmz5UpU8Z9r68JZ9MFt092jMYu8+XLZyVLlrQcOXIkeUxwjoQ0C08/H7kBAID4FdPQ1LhxY1u5cqWb0RZsdevWtZtuuin8fa5cuWz+/Pnhn1m3bp1bYqBhw4butr7qHJGz3ObNm+dCTLVq1cLHRJ4jOCY4h4YA69SpE3WMCsF1OzgGAABkbTGtaSpUqJDVqFEjal+BAgXcmkzB/s6dO7ulAIoXL+6CkGazKcho5pw0bdrUhaMOHTrYoEGDXP1Snz59XHG5eoPk7rvvdrPievXqZbfddpt9/PHHNm3aNDejLqDH6Nixowtq9evXd7P39u/fb506dTqlrwkAAMiYYl4IfjJDhw51M9m0qKVmrGnWm5YmCGhYbdasWdalSxcXphS6FH769+8fPqZixYouIGnNp+HDh1u5cuXslVdececKtG3b1i1RoPWdFLy07IGWI0hYHA4AALKmDLFOUzxgnSYAQFpgnaZTK9Ot0wQAAJDREZoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAA8EJoAAAAyemh68cUXrVatWla4cGG3NWzY0GbPnh2+/+DBg9a1a1crUaKEFSxY0Fq3bm1bt26NOseGDRusRYsWlj9/fitVqpT17NnTjh49GnXMJ598YhdccIHlyZPHKlWqZOPHj0/UllGjRlmFChUsb9681qBBA1uyZEk6PnMAAJDZxDQ0lStXzgYOHGjLli2zpUuX2pVXXmktW7a01atXu/u7d+9u7733nk2fPt0WLlxomzZtslatWoV//tixYy4wHT582BYtWmQTJkxwgahv377hY9avX++OadSoka1YscK6detmt99+u82dOzd8zNSpU61Hjx7Wr18/W758udWuXduaNWtm27ZtO8WvCAAAyKiyhUKhkGUgxYsXt+eee87atGljp512mk2ePNl9L2vXrrWqVava4sWL7cILL3S9Utdee60LU6VLl3bHjBkzxh5++GHbvn275c6d233//vvv26pVq8KP0a5dO9u1a5fNmTPH3VbPUr169WzkyJHu9vHjx618+fJ23333We/evb3avWfPHitSpIjt3r3b9ZoBAJAaFXq/b1nRzwNbxORxU/L5nWFqmtRrNGXKFNu/f78bplPv05EjR6xJkybhY6pUqWJnnnmmC02irzVr1gwHJlEPkV6AoLdKx0SeIzgmOId6qfRYkcdkz57d3Q6OScqhQ4fc40RuAAAgfsU8NK1cudLVK6ne6O6777Z33nnHqlWrZlu2bHE9RUWLFo06XgFJ94m+Rgam4P7gvhMdo5Bz4MAB27FjhwtsSR0TnCMpAwYMcMk02NQzBQAA4lfMQ9O5557rao2+/PJL69Kli3Xs2NHWrFljGd0jjzziuvKCbePGjbFuEgAASEc5LcbUm6QZbVKnTh376quvbPjw4da2bVs3dKbao8jeJs2eK1OmjPteXxPOcgtm10Uek3DGnW5r3DJfvnyWI0cOtyV1THCOpKhnTBsAAMgaYt7TlJCKsFUvpACVK1cumz9/fvi+devWuSUGVPMk+qrhvchZbvPmzXOBSEN8wTGR5wiOCc6h0KbHijxGbdDt4BgAAICcsR7iat68uSvu3rt3r5sppzWVtByA6oQ6d+7slgLQjDoFIc1mU5DRzDlp2rSpC0cdOnSwQYMGuRqkPn36uLWdgl4g1UlpVlyvXr3stttus48//timTZvmZtQF9BgaFqxbt67Vr1/fhg0b5grSO3XqFLPXBgAAZCwxDU3qIbrlllts8+bNLiRpoUsFpquuusrdP3ToUDeTTYtaqvdJs95Gjx4d/nkNq82aNcvVQilMFShQwIWf/v37h4+pWLGiC0ha80nDflob6pVXXnHnCmgoUEsUaH0nBa/zzjvPLUeQsDgcAABkXRlunabMinWaAABpgXWaMu7nd8wLwQEAJ8aHKJAxZLhCcAAAgIyI0AQAAOCB0AQAAOCB0AQAAOCB0AQAAOCB0AQAAOCB0AQAAOCB0AQAAJBeoWnjxo3266+/hm8vWbLEunXrZmPHjk3N6QAAAOIzNP3zn/+0BQsWuO91rTZdK07B6bHHHou67hsAAECWDk2rVq2y+vXru++nTZtmNWrUsEWLFtmkSZNs/Pjxad1GAACAzBmajhw5Ynny5HHff/TRR3b99de776tUqWKbN29O2xYCAABk1tBUvXp1GzNmjH322Wc2b948u/rqq93+TZs2WYkSJdK6jQAAAJkzND377LP20ksv2RVXXGHt27e32rVru/0zZ84MD9sBAADEk5yp+SGFpR07dtiePXusWLFi4f133nmn5c+fPy3bBwAAkLnXaQqFQrZs2TLX47R37163L3fu3IQmAAAQl1LV0/TLL7+4OqYNGzbYoUOH3JIDhQoVcsN2uq16JwAAAMvqPU0PPPCA1a1b13bu3Gn58uUL77/xxhtt/vz5adk+AACAzNvTpFlzWpdJw3GRKlSoYL/99ltatQ0AACBz9zQdP37cjh07lmi/Lq2iYToAAIB4k6rQ1LRpUxs2bFj4drZs2Wzfvn3Wr18/u+aaa9KyfQAAAJl3eG7w4MHWrFkzq1atmh08eNBdi+6HH36wkiVL2ptvvpn2rQQAAMiMoalcuXL2zTff2JQpU+zbb791vUydO3e2m266KaowHAAAIEuHJveDOXPazTffnLatAQAAyOyhSZdI8RVcwBcAACDLhaYbbrjB6zgVhSc1sw4AACBLhCYtMwAAAJBVpfracwAAAFlJqgvB9+/fbwsXLnTXnzt8+HDUfffff39atA0AACBzh6avv/7aLWL5559/uvBUvHhx27Fjh+XPn99KlSpFaAIAAHEnVcNz3bt3t+uuuy58wd4vvvjCfvnlF6tTp449//zzad9KAACAzBiaVqxYYQ8++KBlz57dcuTIYYcOHbLy5cvboEGD7NFHH037VgIAAGTG0JQrVy4XmETDcaprkiJFitjGjRvTtoUAAACZtabp/PPPt6+++soqV65sl19+ufXt29fVNL3++utWo0aNtG8lAABAZuxpeuaZZ+z000933z/99NNWrFgx69Kli23fvt3Gjh2b1m0EAADInD1NdevWDX+v4bk5c+akZZsAAADio6fpwIEDbrmBgGbODRs2zD788MO0bBsAAEDmDk0tW7a0iRMnuu937dpl9evXt8GDB7v9L774Ylq3EQAAIHOGpuXLl9ull17qvn/rrbesTJkyrrdJQWrEiBFp3UYAAIDMGZo0NFeoUCH3vYbkWrVq5ZYguPDCC114AgAAiDepCk2VKlWyGTNmuDWZ5s6da02bNnX7t23bZoULF07rNgIAAGTO0KR1mR566CGrUKGCNWjQwBo2bBjuddIaTgAAAPEmVUsOtGnTxi655BLbvHmz1a5dO7y/cePGduONN4Zv//rrr1a2bNnw6uEAAABZKjSJir+1RdIsukjVqlVz16k7++yzU99CAACADCBdu4BCoVB6nh4AACDj9zQhY6nQ+33Lin4e2CLWTQAAZBEUGwEAAHggNAEAAMQ6NGXLli09Tw8AAHDKUAgOAAAQ60LwNWvWuHWaAAAAskxo0vXlfL399tvua/ny5VPXKgAAgMwamooUKZK+LQEAAIiH0PTaa6+lb0sAAAAyMJYcAAAASM9C8LfeesumTZtmGzZssMOHD0fdt3z58tSeFgAAIH56mkaMGGGdOnWy0qVL29dff+0u1FuiRAn76aefrHnz5mnfSgAAgMzY0zR69GgbO3astW/f3saPH2+9evWys88+2/r27Wt//PFH2rcSQBSuNQgAmaSnSUNyF110kfs+X758tnfvXvd9hw4d7M0330zbFgIAAGTW0FSmTJlwj9KZZ55pX3zxhft+/fr1rAIOAADiUqpC05VXXmkzZ85036u2qXv37nbVVVdZ27Zt7cYbb0zrNgIAAGTOmibVMx0/ftx937VrV1cEvmjRIrv++uvtrrvuSus2AgAAZM7Q9Ouvv0ZdIqVd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vdA16PA/hCakiBYyjLwCuorAV6xYES4K37p1q1t2gHWa4suQIUPc0My9997rrjcYzK7RdaueeuopZtXFIfUca8hGqlev7tbzQXxTb5Mme+hyWFohXEN1/L88GjVNSJGEGZvMnTXoUilak0sL4AWuv/5692GqqeiEpvixbds2a9eunetxCHqQtV6P6l6mTJkStSo8Mn9I+uKLL2zBggXhYbry5cu7YnDVqKpmFdEITQBOSr2LF110UaL92qf7ED80Y0oFwRqWqVq1qtun4faOHTu6WZIankfmp7olhSTNoFM4uuuuu2zy5Ml2+umnx7ppGRorgiNFVPybsACYguD4pwJ/LSuR0NSpU90aTogfc+bMsdGjR4cDk2g2lYZiNWyD+LlIb4kSJVx40nIDV111FYHJAz1NSBENx916661uHY+ggFCF4MFih8HFHhFfdImctm3b2qeffhquaVLtw/z585MMU8i8tGaPLp2TkPbpPsQHDbkqOGlY7tlnn7X27du7yR3qddLMOX1lKDYxCsHxl6YjJ4crpcdnYbAKwteuXetuqyfiwQcfpEA4Di+Zow9UDcNpUof89ttv7tJIxYoV4zqEcUpDsprcEdQ3aR0+9SKvWrUq1k3LUAhNAICwjRs3uiJ/1TSpKFg2bNjgLtY7c+ZMK1euXKybiHSgXsSvvvrKhSZtClAaSWD2XDRCE4BkaWHDk9Ws6f6jR4+esjYh/elj4aOPPgr3KqqmSXUviK+QpFXe1aukkKTh9v3799sZZ5wRXiVcm1YNx/8QmgAk69133z3htchGjBjh/uerv0iRuen91OK01157bXjfhAkTrF+/fu6aZDfccINbeiKoZ0TmpjX2FJLKlCkTDkiqZdLlVZA8QhOAFFm3bp273qAuzqw6l/79+/PXaBxo3ry5+9B8+OGH3e2VK1danTp13FIDql/TavCalq51uZD5afFKBSUVf8MfoQmAl02bNrleB/U+NGvWzAYMGGA1atSIdbOQRjTdXEG4bt267vZjjz1mCxcudLUtMn36dPf+c4kkZGWs0wTghHbv3u16H7RWk4qDtcyAPlwJTPFl586dURdoVWBS71OgXr16rkgcyMoITQCSNWjQIHddwVmzZrkp6Lqopy7IjPijwLR+/frw5TWWL19uF154YdSU9KTWbwKyEobnAJxw9ly+fPmsSZMm7mLNyXn77bdPabuQ9rp06eLW5tFChzNmzHDDsBqSzZ07t7t/0qRJNmzYMDctHciqWBEcQLJ0gV4uk5M1PPnkk9aqVSu3EnTBggVdaAoCk4wbN86aNm0a0zYCsUZPEwAgqoZNoSlhz+Iff/zh9kcGKSCrITQBAAB4oBAcAADAA6EJAADAA6EJAADAA6EJAFKgQoUKbuo9gKyHQnAASIHt27dbgQIFLH/+/LFuCoBTjNAEIEvQKtdMlwfwVzA8ByAuXXHFFXbvvfdat27drGTJku4iw6tWrXLXU9N6Q7psSIcOHWzHjh1Rlwq56aabXE+SLmA7dOhQdx6dI7nhuQ0bNljLli3dOQsXLmz/+Mc/bOvWreH7H3/8cTvvvPPs9ddfdz9bpEgRa9eunXssAJkLoQlA3ApWtf78889t4MCBduWVV9r5559vS5cutTlz5rhwo5AT6NGjhzt25syZNm/ePPvss8/cNdiSc/z4cReYtPCjLnCrn/npp5+sbdu2Ucf997//dZcm0TX8tOlYtQdA5sJlVADErcqVK7uLDstTTz3lAtMzzzwTdWmQ8uXL2/fff+96lhSyJk+ebI0bN3b3v/baa1a2bNlkzz9//nxbuXKlu9CtziMTJ0606tWru2u01atXLxyuxo8fb4UKFXK31cOln3366afT9fkDSFuEJgBxq06dOuHvdTHaBQsWuGG0hNQTdODAATty5IjVr18/vF9Daeeee26y5//uu+9cWAoCk1SrVs2KFi3q7gtCk4blgsAkCmjbtm1Lk+cI4NQhNAGIW6pNCuzbt8+uu+46e/bZZxMdpxDz448/pls7cuXKFXVbF0FW7xOAzIWaJgBZwgUXXGCrV692vT6VKlWK2hSuzj77bBduNKwWefFaDd0lp2rVqrZx40a3BdasWWO7du1yPU4A4guhCUCW0LVrV1ew3b59exeMNCQ3d+5c69Spkx07dswNn3Xs2NF69uzphvEUsDp37mzZs2d3PUNJadKkidWsWdPNuFPB+JIlS+yWW26xyy+/3OrWrXvKnyOA9EVoApAlqKBbM+MUkJo2berCjpYSUP2RgpEMGTLEGjZsaNdee60LRBdffLHrTcqbN2+S51SYevfdd61YsWJ22WWXuZ9Rj9XUqVNP8bMDcCqwuCUAJGP//v12xhln2ODBg12vE4CsjUJwAPg/X3/9ta1du9bNoFM9U//+/d1+rcUEAIQmAIjw/PPP27p169yimFqyQAtcakVxAGB4DgAAwAOF4AAAAB4ITQAAAB4ITQAAAB4ITQAAAB4ITQAAAB4ITQAAAB4ITQAAAB4ITQAAAB4ITQAAAHZy/w9357m038LCgwAAAABJRU5ErkJggg==", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "import pandas as pd\n", + "\n", + "orders_pandas = pd.DataFrame(sales_data)\n", + "\n", + "(\n", + " orders_pandas.groupby(\n", + " [\n", + " \"region\",\n", + " ]\n", + " )[\"sales_income\"]\n", + " .sum()\n", + " .plot(kind=\"bar\", title=\"Total Sales per Region ($)\", ylabel=\"total_sales\")\n", + ")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "344d9c42-8566-43c6-b3e2-c840aa8ab46d", + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.13.1" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/polars_v_pandas/README.md b/polars_v_pandas/README.md new file mode 100644 index 0000000000..60c7018f45 --- /dev/null +++ b/polars_v_pandas/README.md @@ -0,0 +1,26 @@ +The materials contained in this download are designed to complement the RealPython tutorial [Polars vs pandas - What's the Difference](https://realpython.com/polars-vs-pandas-difference/). + +You should create a new folder named marimo on your computer and place each of these files inside it. You may also consider creating a [Python virtual environment](https://realpython.com/python-virtual-environments-a-primer/) within this folder. + +Your download bundle contains the following files: + + + +Online\_Retail.parquet - This parquet file contains retail data used in some of the queries. + +data\_generation.py - This script contains the data\_generation() function used to generate different quantities of data. + +code\_speed\_test.py - This script performs time tests for pandas and Polars DataFrames. + +dataframe\_and\_lazyframe\_time\_tests.py - This script performs time tests for DataFrames and a LazyFrame. + +streaming\_test.py - This script performs time tests for a LazyFrame with streaming enabled. + + + +dataframe\_conversions.py - This file contains the code used to convert between pandas and Polars DataFrames, plus a Narwhals example. + +sample\_pandas\_and\_polars\_code.py - This file contains the code used to illustrate the differences between pandas and Polars syntax. + +DataFrame\_Plots.ipynb - This Jupyter Notebook file contains the plotting code to demonstrate default plotting capabilities. + diff --git a/polars_v_pandas/data_generation.py b/polars_v_pandas/data_generation.py new file mode 100644 index 0000000000..80da9d69be --- /dev/null +++ b/polars_v_pandas/data_generation.py @@ -0,0 +1,19 @@ +import numpy as np + + +def data_generation(number_of_rows): + rng = np.random.default_rng() + + return { + "order_id": range(1, number_of_rows + 1), + "region": rng.choice( + ["North", "South", "East", "West"], size=number_of_rows + ), + "sales_person": rng.choice( + ["Armstrong", "Aldrin", "Collins"], size=number_of_rows + ), + "product": rng.choice( + ["Helmet", "Oxygen", "Boots", "Gloves"], size=number_of_rows + ), + "sales_income": rng.integers(1, 5001, size=number_of_rows), + } diff --git a/polars_v_pandas/dataframe_and_lazyframe_time_tests.py b/polars_v_pandas/dataframe_and_lazyframe_time_tests.py new file mode 100644 index 0000000000..009b50ff54 --- /dev/null +++ b/polars_v_pandas/dataframe_and_lazyframe_time_tests.py @@ -0,0 +1,78 @@ +import functools +import sys +from timeit import Timer + +import pandas as pd +import polars as pl +from data_generation import data_generation + + +def create_pandas_dataframe(test_data): + return pd.DataFrame(test_data).convert_dtypes(dtype_backend="pyarrow") + + +def create_polars_dataframe(test_data): + return pl.DataFrame(test_data) + + +def create_polars_lazyframe(test_data): + return pl.LazyFrame(test_data) + + +def analyze_pandas_dataframe(pandas_df): + pandas_df.groupby( + ["region", "product", "sales_person"] + )["sales_income"].sum() + + +def analyze_polars_dataframe(polars_df): + polars_df.group_by(["region", "product", "sales_person"]).agg( + total_sales=pl.col("sales_income").sum() + ) + + +def analyze_polars_lazyframe(polars_lf): + polars_lf.group_by(["region", "product", "sales_person"]).agg( + total_sales=pl.col("sales_income").sum() + ).collect() + + +test_data = data_generation(int(sys.argv[1])) + +print(f"Pandas dataframe creation time for {int(sys.argv[1])} rows:") +print( + Timer(functools.partial(create_pandas_dataframe, test_data)).timeit(100) +) +print() +print(f"Polars dataframe creation time for {int(sys.argv[1])} rows:") +print( + Timer(functools.partial(create_polars_dataframe, test_data)).timeit(100) +) +print() +print(f"Polars lazyframe creation time for {int(sys.argv[1])} rows:") +print( + Timer(functools.partial(create_polars_lazyframe, test_data)).timeit(100) +) + +print() + +pandas_df = create_pandas_dataframe(test_data) +polars_df = create_polars_dataframe(test_data) +polars_lf = create_polars_lazyframe(test_data) + +print(f"Pandas dataframe analysis time for {int(sys.argv[1])} rows:") +print( + Timer(functools.partial(analyze_pandas_dataframe, pandas_df)).timeit(100) +) + +print() +print(f"Polars dataframe analysis time for {int(sys.argv[1])} rows:") +print( + Timer(functools.partial(analyze_polars_dataframe, polars_df)).timeit(100) +) + +print() +print(f"Polars lazyframe analysis time for {int(sys.argv[1])} rows:") +print( + Timer(functools.partial(analyze_polars_lazyframe, polars_lf)).timeit(100) +) diff --git a/polars_v_pandas/dataframe_conversions.py b/polars_v_pandas/dataframe_conversions.py new file mode 100644 index 0000000000..0699605fe2 --- /dev/null +++ b/polars_v_pandas/dataframe_conversions.py @@ -0,0 +1,29 @@ +import narwhals as nw +import polars as pl +from data_generation import data_generation + +polars_df = pl.DataFrame(data_generation(4)) +polars_df + +pandas_df = polars_df.to_pandas() +type(pandas_df) +pandas_df + +polars_df = pl.from_pandas(pandas_df) +type(polars_df) +polars_df + + +def agnositic_groupby(df): + return ( + nw.from_native(df) + .group_by("region") + .agg(nw.col("sales_income").sum()) + .sort("region") + .to_native() + ) + + +agnositic_groupby(pandas_df) + +agnositic_groupby(polars_df) diff --git a/polars_v_pandas/online_retail.parquet b/polars_v_pandas/online_retail.parquet new file mode 100644 index 0000000000..30f6193e23 Binary files /dev/null and b/polars_v_pandas/online_retail.parquet differ diff --git a/polars_v_pandas/sample_pandas_and_polars_code.py b/polars_v_pandas/sample_pandas_and_polars_code.py new file mode 100644 index 0000000000..56d2b5c7e7 --- /dev/null +++ b/polars_v_pandas/sample_pandas_and_polars_code.py @@ -0,0 +1,36 @@ +import pandas as pd +import polars as pl + +orders_pandas = pd.read_parquet("online_retail.parquet") + +orders_pandas["Total"] = orders_pandas["Quantity"] * orders_pandas["UnitPrice"] + +orders_pandas[["InvoiceNo", "Quantity", "UnitPrice", "Total"]][ + orders_pandas["Total"] > 10 +].head(3) + + +( + orders_pandas + .assign(Total=orders_pandas["Quantity"] * orders_pandas["UnitPrice"]) + .filter(["InvoiceNo", "Quantity", "UnitPrice", "Total"]) + .query("Total > 100") +).head(3) + + +( + orders_pandas.assign( + Total=orders_pandas["Quantity"] * orders_pandas["UnitPrice"] + ).filter(["InvoiceNo", "Quantity", "UnitPrice", "Total"]) + # .query("Total > 100") +).head(3) + + +orders_polars = pl.read_parquet("online_retail.parquet") + +( + orders_polars.select( + pl.col(["InvoiceNo", "Quantity", "UnitPrice"]), + total=pl.col("Quantity") * pl.col("UnitPrice"), + ).filter(pl.col("total") > 10) +).head(3) diff --git a/polars_v_pandas/streaming_test.py b/polars_v_pandas/streaming_test.py new file mode 100644 index 0000000000..0ac3672fe4 --- /dev/null +++ b/polars_v_pandas/streaming_test.py @@ -0,0 +1,38 @@ +import functools +import sys +from timeit import Timer + +import polars as pl +from data_generation import data_generation + + +def create_polars_lazyframe(test_data): + return pl.LazyFrame(test_data) + + +def analyze_polars_lazyframe(polars_lf): + polars_lf.group_by(["region", "product", "sales_person"]).agg( + total_sales=pl.col("sales_income").sum() + ).collect() + + +def analyze_polars_streaming(polars_lf): + polars_lf.group_by(["region", "product", "sales_person"]).agg( + total_sales=pl.col("sales_income").sum() + ).collect(engine="streaming") + + +test_data = data_generation(int(sys.argv[1])) + +polars_lf = create_polars_lazyframe(test_data) + +print() +print(f"Polars lazyframe analysis time for {int(sys.argv[1])} rows:") +print( + Timer(functools.partial(analyze_polars_lazyframe, polars_lf)).timeit(100) +) + +print(f"Polars streaming analysis time for {int(sys.argv[1])} rows:") +print( + Timer(functools.partial(analyze_polars_streaming, polars_lf)).timeit(100) +)