diff --git a/benchmarks/pandas_sum_tricks.ipynb b/benchmarks/pandas_sum_tricks.ipynb index ccf454e..db58109 100644 --- a/benchmarks/pandas_sum_tricks.ipynb +++ b/benchmarks/pandas_sum_tricks.ipynb @@ -1,7 +1,7 @@ { "metadata": { "name": "", - "signature": "sha256:8222de4af96dc6569eddec8d75df6855e8bac273e12e8739fffc42aafd712ba2" + "signature": "sha256:3de4720b58999a1f88844021c43acd1d6d6db6da3315538f9faac86a69424446" }, "nbformat": 3, "nbformat_minor": 0, @@ -22,7 +22,9 @@ "output_type": "stream", "stream": "stdout", "text": [ - "Sebastian Raschka 23/12/2014 \n", + "The watermark extension is already loaded. To reload it, use:\n", + " %reload_ext watermark\n", + "Sebastian Raschka 24/12/2014 \n", "\n", "CPython 3.4.2\n", "IPython 2.3.1\n", @@ -32,7 +34,7 @@ ] } ], - "prompt_number": 1 + "prompt_number": 18 }, { "cell_type": "markdown", @@ -224,7 +226,7 @@ "output_type": "stream", "stream": "stdout", "text": [ - "1000 loops, best of 5: 1.28 ms per loop\n" + "1000 loops, best of 5: 1.37 ms per loop\n" ] } ], @@ -258,7 +260,7 @@ "output_type": "stream", "stream": "stdout", "text": [ - "1000 loops, best of 5: 1.03 ms per loop\n" + "1000 loops, best of 5: 986 \u00b5s per loop\n" ] } ], @@ -292,7 +294,7 @@ "output_type": "stream", "stream": "stdout", "text": [ - "1000 loops, best of 5: 721 \u00b5s per loop\n" + "1000 loops, best of 5: 687 \u00b5s per loop\n" ] } ], @@ -346,7 +348,7 @@ "output_type": "stream", "stream": "stdout", "text": [ - "1000 loops, best of 5: 64.8 \u00b5s per loop\n" + "1000 loops, best of 5: 64.4 \u00b5s per loop\n" ] } ], @@ -408,7 +410,7 @@ "output_type": "stream", "stream": "stdout", "text": [ - "1000 loops, best of 5: 57.2 \u00b5s per loop\n" + "1000 loops, best of 5: 55.7 \u00b5s per loop\n" ] } ], @@ -433,9 +435,321 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Using some simple tricks, the column sum calculation improved from 1280 to 57.2 \u00b5s per loop (approx. 22x faster!)" + "Using some simple tricks, the column sum calculation improved from 1370 to 57.7 \u00b5s per loop (approx. 25x faster!)" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "heading", + "level": 3, + "metadata": {}, + "source": [ + "What about larger DataFrames?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "So, what does this trend look like for larger DataFrames?" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import timeit\n", + "import random\n", + "from numpy import einsum\n", + "import pandas as pd\n", + "\n", + "def run_loc_sum(df):\n", + " return df.loc[:, ['a', 'c', 'd']].sum(axis=0)\n", + "\n", + "def run_einsum(df):\n", + " return [einsum('i->', df[col].values) for col in ('a', 'c', 'd')]\n", + "\n", + "orders = [10**i for i in range(4, 8)]\n", + "loc_res = []\n", + "einsum_res = []\n", + "\n", + "for n in orders:\n", + "\n", + " df = pd.DataFrame()\n", + " for col in ('a', 'b', 'c', 'd'):\n", + " df[col] = pd.Series(range(n), index=range(n))\n", + " \n", + " print('n=%s (%s of %s)' %(n, orders.index(n)+1, len(orders)))\n", + "\n", + " loc_res.append(min(timeit.Timer('run_loc_sum(df)' , \n", + " 'from __main__ import run_loc_sum, df').repeat(repeat=5, number=1)))\n", + "\n", + " einsum_res.append(min(timeit.Timer('run_einsum(df)' , \n", + " 'from __main__ import run_einsum, df').repeat(repeat=5, number=1)))\n", + "\n", + "print('finished')" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "n=10000 (1 of 4)\n", + "n=100000 (2 of 4)" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "n=1000000 (3 of 4)" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "n=10000000 (4 of 4)" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "finished" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n" + ] + } + ], + "prompt_number": 23 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%matplotlib inline" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 24 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "from matplotlib import pyplot as plt\n", + "\n", + "def plot_1():\n", + " \n", + " fig = plt.figure(figsize=(12,6))\n", + " \n", + " plt.plot(orders, loc_res, \n", + " label=\"df.loc[:, ['a', 'c', 'd']].sum(axis=0)\", \n", + " lw=2, alpha=0.6)\n", + " plt.plot(orders,einsum_res, \n", + " label=\"[einsum('i->', df[col].values) for col in ('a', 'c', 'd')]\", \n", + " lw=2, alpha=0.6)\n", + "\n", + " plt.title('Pandas Column Sums', fontsize=20)\n", + " plt.xlim([min(orders), max(orders)])\n", + " plt.grid()\n", + "\n", + " #plt.xscale('log')\n", + " plt.ticklabel_format(style='plain', axis='x')\n", + " plt.legend(loc='upper left', fontsize=14)\n", + " plt.xlabel('Number of rows', fontsize=16)\n", + " plt.ylabel('time in seconds', fontsize=16)\n", + " \n", + " plt.tight_layout()\n", + " plt.show()\n", + " \n", + "plot_1()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "display_data", + "png": "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\nuTJt2rRh0aJFXHzxxZmu0a1bN3744QfatGnD3Llz6dq1KzVq1GDlypX07duXRx99lIEDB7Js2TKG\nDRtGWFgYw4cP9z5+8uTJPProozzyyCNZBhWvvPIKI0aMYOLEifTp04fDhw+zcOFCwAUr1157LVWq\nVCE+Ph5rLcOHD+fPf/4zy5cvz/Vz5attPvbYYzz11FM89dRTTJs2jVtuuYXu3bsTHh7u8xy5eV+d\nPXuWhg0b8t5771G7dm2WLl3KHXfcQa1atbxz1fLbC5X2MYMHDyYxMZHnnnuODh068Msvv5CUlOTz\n2Pyc/9133+XRRx/lhRdeIDY2lnfffZcnn3ySc845J93xGa/TuXNnnn32Wc6ePZvnoYkiIuLbqVOw\nbJnrqfrlF1dWrhx07uzWp8riz1apVmaDq5LinXfeAdzcnlQvv/wydevW5dNPP+XGG2/0+bjTp0+n\n69G64447mD59und/cnIyDz74IM2bNwegSZMm+arf+PHj6datGwB/+9vfuOeee1i1ahXt27cH3Aet\n//73v97jN2/eTKNGjTKdJzXIyIuoqCiioqKYNGkS//vf/3jzzTeJjY0lIiKCQYMGMWjQIM4991wA\nxo4dm6dzHz58mNdff53p06dz6aWXAjB9+nQaNmzoPaZGjRpUqlSJ8uXL5zgEcOrUqYSGhvLee+9R\nrpx726V9zidNmsSDDz5Iv379ALyB3KRJk3jzzTfzVPe0+vbty4gRI1i4cKG3Z+2tt97ixhtvpLxn\nNb60c1MiIyN58cUXad26NSkpKTRo0CBf133ppZdo3759ut6+mTNnUqtWLVasWEGnTp1y1QYjIiLY\ntGmTz2uUL1/eG0zUrFnT+xpMnjyZmJgY72verFkzNm/ezFNPPZUuuIqJicnUq5fR+PHjue+++xgx\nYoS3LLVtf/XVV6xdu5atW7cSEREBwOzZs2nWrBkLFizIsSczO4MGDWLAgAHeOjz77LMsXrzYW5ZR\nbt5X5cqVSzc3KiIigpUrV/L22297g6u8vk+AdP+vbN68mTlz5vD555/Tu3dvwLWp6Oho77/z+l6P\niYlh69at3u0pU6YwZMgQbr/9dgBGjx7NwoUL+Sl1gZQs7iMiIoKjR4+yY8eOLIPUskbrDok/qb2V\nLr//DosWQUICpA4eCAtzadQvucT9u6wqs8FVUfQyFYWVK1eybdu2TBnHjh07lu4DR0aNGjVK95j6\n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\ndTMvXRUS7YuUjq4rdmlZscVRtf+bqyE0dFqcFFt0dHZd+2u7Wxz1auhFIFi8qCg+56rK7d/f1uFv\nw4Y0Y9VqzJi2gmr0aAsqSVLPVNhprJhCorvFycksF2t9VbvW4qWYGZTuFDInsuG/o89vCA2V/i2S\nap7FVSd2725rSLF5c1uHvxBe3+Fv+PDKxqnyc1+CsmS+1a/jtUnuaClYdwqZjtoqr1u2jvOuPK+o\ne7Z+frVrPzNSjg33xe6T6eh+9Vy8+Geb6oXFVV6Mqatfa0OKrVvbzvXqBZdckoqpCRNg0KDKxSlJ\nOjGtbZKLLSROdLlYR4VMMbM8WRcvO/bu4NCuQ11fWKC7syzFFjKd7Wkpdpan9XqXjEmqtLrecxVj\neu7UypWpoNpVsM/ylFNg/Pi05G/8+HQsSepca5vkUs+ydHffS2efXwszLye64T6LtsoWL5JqhXuu\nMnTsGDzxRCqoVq+Gffvazg0alGamrrwSLr7YDn+SqktHbZKrqZCplTbJnRUnpe4c1t3iyOJFkmpf\nXZQPhw+nzn6rVqVOfwcPtp0bPrxt/9T550ND/S6HVidcJ14fCjuNdWdGpLPlXcUuF2t/z00rNjFm\nwpgOP7/ai5fCNsldFSftC5Qs2irbJvn1/LNNWTLfVC96bHH1yitpZmrVqvQsqqNH286deWZbh7+z\nzrLDn5SF1s36xc6ydLTvpRzLxQqvr4Zl0nsO7uGUAx2vQ27faaw7G+6LLXo62yfTVXHUWrxIklTP\netSeqxhh8WJ45BHYtAlaWlqvTc+dai2oRoyoQMBSmbVvk1zqWZbOru9OIVPtWpdmlaqtcXeXlh1v\nBqfeO41JklQs91yVwHPPwV13pbbpAI2NcNllbUv+Tj21svGp9nW3TXKpl4sd75612Ca5q0LiZAqZ\nzpaNHa+QsXiRJEknK/PiKoRwPfBloBH4Rozxix1c80/AW4FXgZtjjCs7u19zM9x/P/z856lZxeDB\n8Pa3p4KqX79yfRcqh/ZtkrsqJE50lqW7hcyWVVsYNX5UTRQvJzIj0tnm/GKXi3WnOHK/S9fcl6Cs\nmGvKkvmmepFpcRVCaAT+BXgTsB1YFkL4aYxxfcE1bwMuiDGOCyFMAb4CTO3ofs88A9/+Nmzblo5n\nzIDf+z3o37/M30iNOl6b5HIsFyu2OGp9Vetm/eeefI4Rl6a1pN0pTk62c1h3iyOLl55h1apV/gNE\n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\nAAAASUVORK5CYII=\n", + "text": [ + "" + ] + } + ], + "prompt_number": 26 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "It looks like that the benefit of calculating the sums separately for each column becomes even larger the more rows the DataFrame has." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Another question to ask: How does this scale if we have a growing number of columns?" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import timeit\n", + "import random\n", + "from numpy import einsum\n", + "import pandas as pd\n", + "\n", + "def run_loc_sum(df, n):\n", + " return df.loc[:, 0:n-1].sum(axis=0)\n", + "\n", + "def run_einsum(df, n):\n", + " return [einsum('i->', df[col].values) for col in range(0,n-1)]\n", + "\n", + "orders = [10**i for i in range(2, 5)]\n", + "loc_res = []\n", + "einsum_res = []\n", + "\n", + "for n in orders:\n", + "\n", + " df = pd.DataFrame()\n", + " for col in range(n):\n", + " df[col] = pd.Series(range(1000), index=range(1000))\n", + " \n", + " print('n=%s (%s of %s)' %(n, orders.index(n)+1, len(orders)))\n", + "\n", + " loc_res.append(min(timeit.Timer('run_loc_sum(df, n)' , \n", + " 'from __main__ import run_loc_sum, df, n').repeat(repeat=5, number=1)))\n", + "\n", + " einsum_res.append(min(timeit.Timer('run_einsum(df, n)' , \n", + " 'from __main__ import run_einsum, df, n').repeat(repeat=5, number=1)))\n", + "\n", + "print('finished')" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "n=100 (1 of 3)\n", + "n=1000 (2 of 3)" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "n=10000 (3 of 3)" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n", + "finished" + ] + }, + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "\n" + ] + } + ], + "prompt_number": 35 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "from matplotlib import pyplot as plt\n", + "\n", + "def plot_2():\n", + " \n", + " fig = plt.figure(figsize=(12,6))\n", + " \n", + " plt.plot(orders, loc_res, \n", + " label=\"df.loc[:, 0:n-1].sum(axis=0)\", \n", + " lw=2, alpha=0.6)\n", + " plt.plot(orders,einsum_res, \n", + " label=\"[einsum('i->', df[col].values) for col in range(0,n-1)]\", \n", + " lw=2, alpha=0.6)\n", + "\n", + " plt.title('Pandas Column Sums', fontsize=20)\n", + " plt.xlim([min(orders), max(orders)])\n", + " plt.grid()\n", + "\n", + " #plt.xscale('log')\n", + " plt.ticklabel_format(style='plain', axis='x')\n", + " plt.legend(loc='upper left', fontsize=14)\n", + " plt.xlabel('Number of columns', fontsize=16)\n", + " plt.ylabel('time in seconds', fontsize=16)\n", + " \n", + " plt.tight_layout()\n", + " plt.show()\n", + " \n", + "plot_2()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "display_data", + "png": "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\n2bIlv/32G1u3bs223oSEBLp3705CQgJdunTx6/42b97M7t276dWrl6+sZMmSdOnShe+++477778f\ngLi4OObPn8/mzZvTnP/kk0/y0ksvUbVqVR555BHuuOOOgKUUptevXz9atmzJW2+9RbFixfjpp58o\nWbJkjusZNWoUr7/+OmXLlqVfv3707duXEiVK8P777xMWFsYtt9zC6NGjmTBhAgCJiYlER0dTqVKl\nNPWUKVOGSZMmUaNGDX7++WceeOABSpQowbPPPgvAv//9b5o1a8b48eN5/PHHGTJkCCVLlmT8+PGZ\ntuu1117js88+46OPPiImJobt27enCYQeeOABpk6dmu29rVu3jpo1a7J48WLKlClDhw4dfPs6duxI\nZGQkixcv5pJLLgGgdOnSNGnShPnz56c5VkSCQ/NfJNjU5yQQTp+GpUshPh68SxGEhUGrVtCtG7zz\nTmCuq+Aqnzty5AgTJ05k0qRJvhGHSZMmpZlTVaFCBUqVKkVERASVK1f2q95XXnmFrl27MnLkSADq\n169PUlISL774Ig8//DBJSUl89NFHfP31176gJyYmhk6dOmVbb2RkpG/kxF+7du0CoEqVKmnKK1eu\nTHJysm+7evXq1K9fP8P5Y8aM8c07euaZZ+jUqRPJyclUr17d7zbk1rZt2xg6dKgvMKhbt26u6hkz\nZgyXX3454AKWwYMHs3z5clq0aAG4QPfjjz/2HZ+UlETt2rUz1PP3v//d92/vKNM//vEPX3BVrVo1\n3nvvPW699VYOHTrEtGnTWLJkCSVKlMjy/i655BLf+16zZs00Ac+YMWMYNmxYtvdWrVo1wL3P6YNB\nYwyVK1f29YHUbU8dxImIiIj448ABmD8fFiwA7+ySMmWgc2e44gqoUCGw11dwlc6FjDAFwq+//sqp\nU6fSfKCNjIykadOmF1Tv+vXrue6669KUXX755YwePZojR46wYsUKwsLC6NatW47qbdOmTZ6OGqWe\nD5U+bdGrWbNmvn97P8jv2bOH6tWrU6ZMGV8d/fv355///GeetQ3gscce495772XKlCn06NGDPn36\ncOmll+a4ntT34A2QU7/HlStXZs+ePb7tw4cPExkZmaGejz/+mAkTJvDrr79y5MgRzp49y7lz59Ic\nc+ONN3L77bfz/PPP8/LLL2fbl+Li4ujZsyeXXHIJvXr14pprruHqq6/2vaaVKlXKEDDlhaioqDQL\nXYhI8CQkJGgkQYJKfU4ulLWwcSPMmwcrVoD3o0+tWtC9O7RuDRERwWmL5lwVUNbagNUR7NXxqlat\nCsDu3bvTlO/evdu3LzsRqX5avG33BhSrV69m1apVrFq1yjd6k5dGjhzJ2rVruemmm/juu+9o1qwZ\nkyZNAvAtKpL6dT59+rTf95B6UQljTJogqVy5chkW+/j++++5/fbbufrqq/niiy9YuXIlzz33HKdO\nnUpz3IkTJ1iyZAnFihUjKSkp2/tr2bIlW7ZsYdy4cZw7d4677rqLnj17+u7pgQceICoqKtuv3377\nDXDv8969e9PUb61lz549Gd7nw4cPUyHQf1oSERGRAu30aVi0CJ5/HsaPh2XLXHnr1jBsmJtj1aFD\n8AIr0MhVvlevXj0iIiJYvHgxMTExABw9epQ1a9bQoEGDXNfbqFEjFi1alKZs4cKFREdHExkZSYsW\nLTh37hzx8fFceeWVF3IL51WnTh2qVq3KnDlzaNWqFeACgIULF2Y5F8hfuU3Ty4n69eszePBgBg8e\nzIMPPsh7773HwIEDfSM6ycnJVKxYEYCVK1fm2TVnzJiRpmzRokXUqFGDp556yle2ZcuWDOcOHTqU\n06dPM2fOHK688kquvfZarr/++iyvVaZMGfr06UOfPn2Ii4ujffv2/Prrr9SvXz9HaYEdOnTgyJEj\nLF682DcSu3jxYo4ePUrHjh3TnLN161ZfmqSIBJdGECTY1Ockp/bvd6l/CxempP5FRUGXLu6rfPnQ\ntU3BVT5XpkwZ7rnnHoYPH06lSpWoVq0azz77bIZUr/RGjBjBkiVLmDt3bqb7//a3v9GmTRtGjx7N\n7bffzpIlS3jllVd8KxFecskl9O3bl3vvvZdXX301zYIWd955Z5bX/fHHHxkwYAAffPABbdq08ese\njTE8+uijjB07loYNG9KgQQOee+45oqKi6Nevn9/3lBPeIOfQoUOEhYWxcuVKihcvTuPGjbM9r0eP\nHrRr146xY8dy/PhxHn/8cfr27Uvt2rXZvXs3CxcupH379oALgKKjoxk1ahQvvPACmzdv5rnnnrvg\ntgN07tyZBx98kL179/qCuEsvvZQdO3Ywbdo02rdvz+zZs5k+fXqa87766iveeecdFi5cSJs2bRg1\nahT33nsvq1evzjDnDdzcvOrVq9O8eXMiIiKYOnUq5cqV8835y0laYKNGjbjqqqsYNGgQ77zzDtZa\nBg0axPXXX5/mDwXHjh1j7dq1fi+IIiIiIoWftZCU5FL/Vq5MSf2rXdul/rVqFdwRqqwouCoAxo8f\nz9GjR+nduzeRkZEMHjyYY8eOpTkm/UOFd+3axaZNmzIc49WyZUtmzJjByJEjGTt2LFWrVmXEiBE8\n9NBDvmP+/e9/8/TTTzNkyBD27dtHzZo1eeyxx7Jt67Fjx0hKSuL48eO+slGjRp03IBw2bBjHjx/n\noYce4sCBA7Rv3545c+akmVd0vnvKriy92NhY37HWWv73v/8RExOTof70Nm3a5FtIolixYhw8eJC4\nuDh27txJxYoVuf76632jbREREUyfPp0HH3zQ93DccePGZRgl8uce0r+/TZo0oWnTpnz++efce++9\nAFx33XUMHTqURx99lOPHj3PllVfy7LPP+t7TvXv3cvfdd/P000/7At8nnniC2bNnc/fdd/Pll19m\nuHbZsmV5+eWXSUpKwhhDbGwsX331Va5WRASYNm0agwcP9o2G3njjjbzxxhtpjvnyyy+Jjo7WSoEi\nIaL5LxJs6nOSnVOn4McfXVDlmWlAeDi0aeOCqjp1IMgzWrJl8mLuTn5ijLHZzSUqbPcbKt4l1/fu\n3etLecvKXXfdxZ49e/jqq6+C1Lq8ExMTw5AhQ84bVIbCe++9x6RJkzKkdxZ0119/PV26dGHo0KGh\nborIBSuIv3f0QVeCTX1OMvP77ympf0ePurKyZd2qf3mR+uf5/znPwzKNXEmueEc3YmJi6NWrF598\n8kmmx1lrmTdvHvHx8cFs3gUbO3Ys48aNSzMCl98MHDiQ8ePHM3/+fN9S9AXd6tWrWblyZYb5ZCIS\nPPqQK8GmPide3tS/+HhYtSol9S8mxj2bqnVrKJbPoxeNXEmunDhxwvcMqsjIyEzn6xRkBw4c4MCB\nAwBUrFiRcuXKhbhFIlIQ6feOiMj5nToFP/zgUv927HBl4eFuHpU39S+vBWrkSsGViIhIgBTE3ztK\n0ZJgU58run7/HRIS3HLqqVP/vKv+BfJv20oLFBERERGRAs1a+OUXN0q1enVK6l+dOm6UKjY2/6f+\nZUcjVyIiIgGi3zsiIs7Jkympf56ZJYSHu3lU3bu7eVXBpJErEREREREpUPbtS0n98z5JqFw5uOIK\nt/Jf2bIhbV6eU3AlIiIiPpr/IsGmPlf4WAvr16ek/nkH8OvVc6v+tWxZsFP/slNIb0tERERERILp\n5En4/nsXVO3c6cqKFXMP/O3WDWrXDm37giEs1A2Q8+vatSthYWGEhYXx448/+n3e5MmTiYqKCmDL\n8taZM2do2LAh8+fPz3T/li1bCAsLY/ny5UFu2fldd911DBw40Ld97Ngxbr75ZsqXL094eDhbt24l\nJiaGsLAwwsPD2bNnT55dOywsjJkzZ6bZDgsLC/h7H4r3Y9WqVURHR3PixInzHvv555/ToEEDIiIi\nuPvuu4PQOv/587NZp04dXnnllSC1KLQ2bdpE5cqVOXz4cKibkqlZs2bRqlWrDOXen+mwsDD2798f\ngpYFhkYQJNjU5wq+PXvgv/+F4cNh2jQXWJUvDzfeCC+8AHFxRSOwghAEV8aYq4wx640xScaY4dkc\n18YYc8YY0yen5xY2xhjuvvtudu3aRWxsrN/n3XbbbWzevDmALctbkydP5uKLL07zQNywsDC2bdsG\nQK1atdi1axfNmzfPs2uOGjUqTVCUW8YY34OVASZOnMiCBQtYtGgRO3fuJDo6GmMMI0eOZOfOnVSq\nVOmCr5mVXbt2MWHChIDVH0rNmzenZcuWvP766+c99p577uGWW25h27ZtvPrqq0FoXd5aunQpf/nL\nX0LdjKB45plnuP/++ymbKvH+p59+4oorrqB06dLUrFmTMWPGBOz6jzzyCG3atKFkyZLUyeRhKjfc\ncANnzpzJ8HDrZcuWZfkAdRGRws5aWLsW3ngDnnkGvv0Wjh+H+vXhvvtg7Fi45hooQH/nzxNBTQs0\nxoQDbwB/AnYAS4wxs6y16zI57kXg65yeW1iVLl2aypUr5+ickiVLUrJkyQC1KO+98cYbDB48OMv9\nYWFh530NTp48yeHDh/0OXlIHRHlp48aNNGrUiCZNmqQpj4qKyvH7mFOVK1dO8yG1sBkwYADDhg1j\n6NChWR5z4MAB9u/fT69evahWrVqur3Xq1CmKFy+e6/MvRMWKFfO8zlDeT1b27NnDjBkzWLt2ra/s\n8OHD9OzZk65du7J06VLWrVvHwIEDiYyM5LHHHsvzNlhriYuLY/Xq1XzzzTeZHtO/f3/efPNNbrnl\nFl9ZxYoVqVChQp63J9Q0/0WCTX2uYDlxAhYvdotU7NrlyiIiUlL/atUKafNCLtgjV22BjdbaLdba\n08B04MZMjhsMfAzszcW5RcaOHTu47bbbuOiii7jooou47rrr2Lhxo29/+tSjUaNG0bRpU6ZPn069\nevUoW7YsvXv35vfff/cd89NPP9GjRw/KlStHVFQULVq0ICEhAXD/+aVPf0mfGuY95uuvvyY2NpbS\npUvTpUs7UocbAAAgAElEQVQXduzYQXx8PM2aNSMqKoobbriBAwcO+OpZu3Ytq1ev5oYbbsjyfv1J\nQ9u1axc1a9bkpptuYubMmZw6dSrb1zA3SyQfO3aMuLg4oqKiqFq1KuPGjUuzv2vXrrz22mskJiYS\nFhZG9+7ds61v/fr13HDDDZQvX56oqCg6duzImjVrfO0bM2YM0dHRlCxZkmbNmjFr1qwctzm9jh07\n8vjjj6cpO3z4MKVKleKzzz4D4MMPP6RNmzaULVuWKlWq0LdvX5K9a6dmwp/+Ae69vvbaa3319uvX\nj927d/v2Z9cHAa655hp+++03Fi9enGU7vIFJ9+7dCQsLIzExEYCZM2fStGlTSpYsSa1atRg7dmya\nc2NiYhg9ejR33303FSpUoH///lne75QpU3x1Va1albi4ON++bdu20bt3b8qWLUvZsmXp06cPO7yP\nnPdTTEwM//jHP3zbYWFhvPvuu9xyyy2UKVOGevXqMXXq1GzriIuL4/rrr+fFF1+kZs2a1PL8xjvf\ne+t9L+Pj42nXrh2RkZG0adOGFStWpKl/4sSJ1KpVi8jISHr37s1bb71FWFjaXyv/+9//aNWqFaVK\nlaJu3br8/e9/5/Tp0779H3/8MfXr16devXq+sqlTp3LixAmmTJlC48aN6dOnD8OHDz9vmmRuXiOA\n1157jYceeogGDRpk+X/CDTfcQGJiIju9kwhERIqYPXvgo49c6t/06S6wqlABbroJxo2Du+5SYAXB\nD65qANtTbf/mKfMxxtTABU1veYq8v+nOe25RcuzYMbp160bp0qVJTEzk+++/p1q1avzpT3/i+PHj\nWZ63ZcsWZsyYweeff86cOXNYsWIFTz31lG9/v379qFGjBkuWLGHVqlWMHj06V6Nfo0aN4vXXX+eH\nH37gwIED9O3bl+eee47333+fhIQE1qxZw+jRo33HJyYmEh0dnWHEKacjS7Vr12bx4sXUqVOHBx98\nkOrVq/Pwww9nOVctfTqfPx5//HHmzp3LzJkz+fbbb1mxYoXvwzvAp59+ysCBA+nYsSO7du1KMx8q\nveTkZDp16kR4eDhz585l1apVPPLII5w9exaACRMmMH78eF5++WXWrFlD7969+fOf/8yqVaty1Ob0\n+vfvz/Tp09N8kPzkk08oXbo01157LQCnT59mzJgxrF69mi+++IJ9+/Zx++23X9B1d+7cSZcuXWjW\nrBlLlizh22+/5ciRI9x4Y8rfSc7XB0uXLk2TJk2ynJt3+eWX8/PPPwMumNq1axcdOnRg2bJl9O3b\nl5tvvpk1a9bwwgsvMG7cON54440057/yyis0btyYZcuWZQi+vN5++20eeOAB7rnnHtasWcPXX3/t\nS1c9d+4cN954I3v37iUhIYF58+aRnJzMTTfdlKPXKrO++eyzz9K7d29Wr17Nrbfeyt1338327duz\nqMGZP38+a9asYc6cOXz77beA/+/tk08+yUsvvcTy5cupWLEid9xxh2/f4sWLue+++xg8eDCrVq3i\n2muvZeTIkWnaPHv2bO68806GDBnC2rVrmThxIh9//DFPPvmk75jExETatGmT5rqLFy+mc+fOlChR\nwlfWq1cvkpOT2bp1a7b3m5vXyB8NGjSgfPnyWfa7wkQjCBJs6nP5l7WwZg28/jo8/TTEx7uRqwYN\nYNAgl/p39dVFL/UvO8FeLdCfYYIJwBPWWmvcb2nvb+qgPIVx0P8GBaTet69/O0/rmz59OuD+cuz1\nr3/9iypVqvDFF1+kSV1J7cyZM2lGtO6//34mTZrk279t2zaGDh3KJZdcAkDdunVz1b4xY8Zw+eWX\nA/DAAw8wePBgli9fTosWLQC46667+Pjjj33HJyUlUTuTmY7eICMnYmNjiY2NZfz48cyePZsPPviA\nbt26UatWLQYMGMCAAQOoUcPF5SNHjsxR3UeOHGHixIlMmjSJnj17AjBp0iRq1qzpO6ZChQqUKlWK\niIiI86YAvvnmm0RFRTFjxgyKedYkTf2ajx8/nqFDh3LbbbcBMHr0aBITExk/fjwffPBBjtqeWt++\nfXn00UeZN2+eb2Rt6tSp3HLLLURERACkmYsWExPDP//5Txo3bkxycjLVq1fP1XXfeustWrRokWa0\nb8qUKVSsWJGlS5fSunVrv/pgrVq12LBhQ6bXiIiI8AXpF110ke89eOWVV+jatavvPa9fvz5JSUm8\n+OKLPPzww77zu3btmmFUL70xY8bw17/+lUcffdRX5u3b3377LT/99BObNm3yjRRNmzaN+vXrEx8f\nf96RzOwMGDCAfv36+drw6quvsmDBAl9ZZkqVKsXEiRN97yv4/96OGTPGNwfymWeeoVOnTr5jXnvt\n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\n9PTpQCA1OT8ZmFtbWZsZSDXFWNuwlojThV0iIiIiUtwUXOXZwkJmlmpRZ6cPqHbsgPr68NaXa2bG\n0NRQIJCaic8E5tZX1bOheUNGRqq9rr0oL+NVPbiEQftOwqB9J4WmPSflRMFVngwN+SzV/v0wMeHH\nqqp8x7+77oJNm0o/S5W0JIMTg4HLeGcXZgNzm6qb2NCyIeMOqbbatqIMpERERERELofOXOVQPA4H\nD/os1csvp8e7u32Wavt2qCvRq5QWkgsMTAwEAql4Ih6Y21rbupSRWrxDqqWmJYRVi4iIiIgE6cxV\nERsc9Fmqxx6DydQxoqoqH0zt2gUbNpRWliqeiNM33pcRSPVP9JNIJgJz2+vbM85HrW9eT2P1Cu0Z\nLyIiIiIrmoKryxSPw1NP+SzVq6+mx9evT2epakrgntq5hTl6xzMv4x2cGCRpycDctQ1rAxmpusoS\nTcVdItWDSxi07yQM2ndSaNpzUk4UXF2igQEfUD32GExP+7GaGnjTm9JZqmI1HZ+mdywzkBqaGuLs\nMsqIi2RextsUI9Yco6aiBKJFEREREZGQ6MxVFubn4cc/9kHVkSPp8Y0bfUB1223Fl6Va7Np3ZPgI\nR0aOcGT4CCcmTwTmRSNROhs7MzJS3U3dVEWrQli1iIiIiEj+6cxVCPr6fED1+OMwk+okXlPj26fv\n2gWxWLjrWy6eiHN09OhSIHVk5AhT81MZcyqjlXQ1dmV07etq6qIiom0gIiIiInKl9F31Webm4Mkn\nfVD1+uvp8auuSmepqqvDW9+i8bnxpSDq8PBhjo8dDzScaK5pZkvbFja1bmJL2xa6m7oVSF0m1YNL\nGLTvJAzad1Jo2nNSTvSddsrx477j3+OPw2zqmqbaWti5099L1d0d3trMjIGJgYys1KmpUxlznHN0\nN3WzuW0zm1s3s7ltM6tqV+keKRERERGRAlnRZ65mZ+GJJ3yW6tix9PiWLT6geuMbfUv1QptbmOP1\n0dc5MnyE10Ze48jIEWbiMxlzqiuq2dS6ic2tm9nUuolNrZuorawt/GJFREREREqMzlzliJkPpB5+\nGA4c8GWAAPX16SxVZ2dh1zQyM5KRleod6w20Qm+rbVvKSm1p20JXUxcRFynsQkVERERE5LxWTHA1\nM+ODqX37oLc3PX7NNf4s1S23QGVl/teRtCT94/0cHj68FFANzwxnzIm4COub17OlbctSQNVa25r/\n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\nAABJRU5ErkJggg==\n", + "text": [ + "" + ] + } + ], + "prompt_number": 37 + }, { "cell_type": "markdown", "metadata": {}, diff --git a/pandas_sum_tricks.ipynb b/pandas_sum_tricks.ipynb new file mode 100644 index 0000000..ccf454e --- /dev/null +++ b/pandas_sum_tricks.ipynb @@ -0,0 +1,450 @@ +{ + "metadata": { + "name": "", + "signature": "sha256:8222de4af96dc6569eddec8d75df6855e8bac273e12e8739fffc42aafd712ba2" + }, + "nbformat": 3, + "nbformat_minor": 0, + "worksheets": [ + { + "cells": [ + { + "cell_type": "code", + "collapsed": false, + "input": [ + "%load_ext watermark \n", + "%watermark -d -v -a 'Sebastian Raschka' -p numpy,pandas" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "Sebastian Raschka 23/12/2014 \n", + "\n", + "CPython 3.4.2\n", + "IPython 2.3.1\n", + "\n", + "numpy 1.9.1\n", + "pandas 0.15.2\n" + ] + } + ], + "prompt_number": 1 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
" + ] + }, + { + "cell_type": "heading", + "level": 1, + "metadata": {}, + "source": [ + "4 Simple Tricks To Speed up the Sum Calculation in Pandas" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "I wanted to improve the performance of some passages in my code a little bit and found that some simple tweaks can speed up the `pandas` section significantly. I thought that it might be one useful thing to share -- and no Cython or just-in-time compilation is required! " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
\n", + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In my case, I had a large dataframe where I wanted to calculate the sum of specific columns for different combinations of rows (approx. 100,000,000 of them, that's why I was looking for ways to speed it up). Anyway, below is a simple toy DataFrame to explore the `.sum()` method a little bit." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "df = pd.DataFrame()\n", + "\n", + "for col in ('a', 'b', 'c', 'd'):\n", + " df[col] = pd.Series(range(1000), index=range(1000))" + ], + "language": "python", + "metadata": {}, + "outputs": [], + "prompt_number": 2 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "df.tail()" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
abcd
995 995 995 995 995
996 996 996 996 996
997 997 997 997 997
998 998 998 998 998
999 999 999 999 999
\n", + "
" + ], + "metadata": {}, + "output_type": "pyout", + "prompt_number": 3, + "text": [ + " a b c d\n", + "995 995 995 995 995\n", + "996 996 996 996 996\n", + "997 997 997 997 997\n", + "998 998 998 998 998\n", + "999 999 999 999 999" + ] + } + ], + "prompt_number": 3 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's assume we are interested in calculating the sum of column `a`, `c`, and `d`, which would look like this:" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "df.loc[:, ['a', 'c', 'd']].sum(axis=0)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 4, + "text": [ + "a 499500\n", + "c 499500\n", + "d 499500\n", + "dtype: int64" + ] + } + ], + "prompt_number": 4 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, the `.loc` method is probably the most \"costliest\" one for this kind of operation. Since we are only intersted in the resulting numbers (i.e., the column sums), there is no need to make a copy of the array. Anyway, let's use the method above as a reference for comparison:" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "# 1\n", + "%timeit -n 1000 -r 5 df.loc[:, ['a', 'c', 'd']].sum(axis=0)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "1000 loops, best of 5: 1.28 ms per loop\n" + ] + } + ], + "prompt_number": 5 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Although this is a rather small DataFrame (1000 x 4), let's see by how much we can speed it up using a different slicing method:" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "# 2\n", + "%timeit -n 1000 -r 5 df[['a', 'c', 'd']].sum(axis=0)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "1000 loops, best of 5: 1.03 ms per loop\n" + ] + } + ], + "prompt_number": 6 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Next, let us use the Numpy representation of the `NDFrame` via the `.values` attribue:" + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "# 3\n", + "%timeit -n 1000 -r 5 df[['a', 'c', 'd']].values.sum(axis=0)" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "1000 loops, best of 5: 721 \u00b5s per loop\n" + ] + } + ], + "prompt_number": 7 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "While the speed improvements in #2 and #3 were not really a surprise, the next \"trick\" surprised me a little bit. Here, we are calculating the sum of each column separately rather than slicing the array." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "[df[col].values.sum(axis=0) for col in ('a', 'c', 'd')]" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 8, + "text": [ + "[499500, 499500, 499500]" + ] + } + ], + "prompt_number": 8 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "# 4\n", + "%timeit -n 1000 -r 5 [df[col].values.sum(axis=0) for col in ('a', 'c', 'd')]" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "1000 loops, best of 5: 64.8 \u00b5s per loop\n" + ] + } + ], + "prompt_number": 9 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In this case, this is an almost 10x improvement!" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "One more thing: Let's try the Einstein summation convention [`einsum`](http://docs.scipy.org/doc/numpy/reference/generated/numpy.einsum.html)." + ] + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "from numpy import einsum\n", + "[einsum('i->', df[col].values) for col in ('a', 'c', 'd')]" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "metadata": {}, + "output_type": "pyout", + "prompt_number": 10, + "text": [ + "[499500, 499500, 499500]" + ] + } + ], + "prompt_number": 10 + }, + { + "cell_type": "code", + "collapsed": false, + "input": [ + "# 5\n", + "%timeit -n 1000 -r 5 [einsum('i->', df[col].values) for col in ('a', 'c', 'd')]" + ], + "language": "python", + "metadata": {}, + "outputs": [ + { + "output_type": "stream", + "stream": "stdout", + "text": [ + "1000 loops, best of 5: 57.2 \u00b5s per loop\n" + ] + } + ], + "prompt_number": 11 + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + }, + { + "cell_type": "heading", + "level": 3, + "metadata": {}, + "source": [ + "Conclusion:" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using some simple tricks, the column sum calculation improved from 1280 to 57.2 \u00b5s per loop (approx. 22x faster!)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "
" + ] + } + ], + "metadata": {} + } + ] +} \ No newline at end of file