From 516288be3f9ee853a74e67622a9968352ef069a5 Mon Sep 17 00:00:00 2001 From: Kjartan Thor Wikfeldt Date: Mon, 12 Nov 2018 22:25:17 +0100 Subject: [PATCH] add exercise on R+python --- exercises.ipynb | 40 ++- solutions.ipynb | 780 +++++++++++++++++++----------------------------- 2 files changed, 351 insertions(+), 469 deletions(-) diff --git a/exercises.ipynb b/exercises.ipynb index 8ef6436..13bb64a 100644 --- a/exercises.ipynb +++ b/exercises.ipynb @@ -141,7 +141,7 @@ "4. The \"share\" column of the dataframe contains the number of Nobel recipients that shared the prize. Have a look at the statistics of this column using \n", "\n", "```python\n", - "nobels[\"share\"].describe()\n", + "nobel[\"share\"].describe()\n", "```\n", "\n", "5. The `describe()` method is smart about data types. Try this: \n", @@ -161,15 +161,14 @@ "7. Next subtract the birth date from the year of receiving the prize and insert it into a new column \"age\":\n", "```python\n", "nobel[\"age\"] = nobel[\"year\"] - nobel[\"born\"].dt.year\n", - "nobel[[\"surname\",\"age\"]].head(10)\n", "```\n", " - Now print the \"surname\" and \"age\" of first 10 entries using the `head()` method.\n", "\n", "8. Now plot results in two different ways:\n", "\n", "```python\n", - "nobel[\"age\"].plot.hist(bins=[20,30,40,50,60,70,80,\n", - " 90,100],alpha=0.6);\n", + "nobel[\"age\"].plot.hist(bins=[20,30,40,50,60,70,80, 90,100],alpha=0.6);\n", + "\n", "nobel.boxplot(column=\"age\", by=\"category\")\n", "```\n", "\n", @@ -340,6 +339,39 @@ "Final note: While parallelizing Python code is often worth it, there are other ways to get higher performance out of Python code. In particular, fast numerical packages like [Numpy](http://www.numpy.org/) should be used, and significant speedup can be obtained with just-in-time compilation with [Numba](https://numba.pydata.org/) and/or C-extensions from [Cython](http://cython.org/).\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### *Exercise 6:* Mixing Python and R " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Your goal now is to define a pandas dataframe, and pass it into an R cell and plot it with an R plotting library.\n", + "\n", + "1. Run the following code in a code cell and plot it with the basic plot method of pandas dataframes:\n", + "\n", + "```python\n", + "import pandas as pd\n", + "df = pd.DataFrame({\n", + " 'cups_of_coffee': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n", + " 'productivity': [2, 5, 6, 8, 9, 8, 0, 1, 0, -1]\n", + "})\n", + "```\n", + " \n", + "2. Now take the following R code, and use the `%%R` magic command to pass in and plot the pandas dataframe defined above:\n", + "\n", + "```R\n", + "library(ggplot2)\n", + "ggplot(df, aes(x=cups_of_coffee, y=productivity)) + geom_line()\n", + "```\n", + "\n", + "3. Play around with the flags for height, width, units and resolution to get a good looking graph." + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/solutions.ipynb b/solutions.ipynb index 8b4c779..3a3a326 100644 --- a/solutions.ipynb +++ b/solutions.ipynb @@ -22,7 +22,7 @@ { "data": { "application/vnd.jupyter.widget-view+json": { - "model_id": "507fc8f4df9f4346b07ffe2cfbe9d384", + "model_id": "ef39542623514e52ad0ea5011b911823", "version_major": 2, "version_minor": 0 }, @@ -83,7 +83,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -99,7 +99,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -108,7 +108,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -119,7 +119,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -144,7 +144,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -161,17 +161,19 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 7, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYwAAAD8CAYAAABkbJM/AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDMuMC4xLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvDW2N/gAAIABJREFUeJzt3Xd4VFX6B/Dvmy4lQEjoJXSkC5GOoCAiqNhwbSu6ltV1/a1t17goKIqyNlbXytrQtWNDA9KL0oP0HnpoCQQILZByfn/MncmdmXtn7mRmMiXfz/Pkyb1nzr1zhgnzzr3nnPeIUgpERETexIS6AUREFBkYMIiIyBIGDCIisoQBg4iILGHAICIiSxgwiIjIEgYMIiKyhAGDiIgsYcAgIiJL4kLdgEBKTU1V6enpoW4GEVFEWbVq1RGlVJq3elEVMNLT05GdnR3qZhARRRQR2WOlHm9JERGRJQwYRERkCQMGERFZwoBBRESWMGAQEZElDBhERGQJAwYREVnCgEFVzrrc43hi6rpQN4Mo4jBgUJVzzZuL8VX2PhQVl3qtm56ZhfTMrEpoFVH4Y8CgKiv/5LlQN4EoojBgUJX1+tztoW4CUURhwKAqa+qqXKf9F6dvxisztzr2c/JOVXaTiMJaVCUfJPJkz9HTKFPmj7+3aCcA4PEr2gEAPl26O/iNIoogDBhUJewrOIOBLy9wK1dKQUQMj5mytDyBZ3FpGeJjeUFOVRv/B1CVMOCl+Ybli7YfsXR8SamHSxOiKoIBg6q0hNgYbD10Eqv2HPNYb9R7SyqpRUThi7ekKOqt3F1g+tjmg4UY//Mmw8cGtUvDgq35AIAN+wuD0jaiSMIrDIp6o95davrYh4t3uZVtO3wSABzBwu7IKc7boKqNAYOqtILT593KfjXp18h4fg5KSsuC3SSisMWAQVXamfPu6UFqJMaa1v/LZ78HszlEYY0Bg6LSoRNFSM/Mwj+mrjV8/KHLWpseWzMp3vSxWZsO48TZYr/bRxSJGDAoKvV+cS4A4Ovs8tncf+zd3LF9a69mpsf+5bPfsa/gDIZ1bIC29Wu4Pd712VkBbClR5GDAoCpj/MiOju0EL5PwBrw0H6v2HkNcDP+LENlxWC1VGSKCL+7tDQCoWyPRa/38k+fQqFZSsJtFFDH49Ymi0sND2hiW92lVF31a1bV8nsOFHEpLZMeAQVHp33N8S10eH2ucT+pQYVEgmoPLXl2AR79eE5BzEYUKAwYRgPS61X2qf/Z8Kc6XWJ+TsTP/NL77fb+vzSIKKwEJGCIyTES2ikiOiGQaPJ4oIl9pjy8XkXTdY09q5VtF5Apd+YcikiciGwLRRiJPPrrrYky4rpPhYxuetf1ZVk+wzc+4pWczXDj2F7R9agbOnC/xem6uq0HRwu+AISKxAN4CcCWADgBuEZEOLtXuBnBMKdUawCQA/9KO7QDgZgAdAQwD8LZ2PgD4WCsjCqrZj1yCJnWq4bZezQ0fr5EYhyeGtce3f+mLtJrOneWZ3673en4ra4cTRYJAXGH0BJCjlNqplDoP4EsAI13qjAQwRdueCmCw2BYhGAngS6XUOaXULgA52vmglFoEwDxrHJEP7uybbvpYm/o1Hdu/P32502MD2qQCAB4Y1ArtGyQj/+Q5fLFir+PxpTuPen3uHfm8wqDoEIhhtY0B7NPt5wLoZVZHKVUiIicA1NXKl7kc2zgAbaIqTP+NfstzwzB1VS5u6ek+UW/Oo5cg76TzKKiU6glO+2v2Hvf4XPna8buOnMZVb/yKOY8NRMNaFzjV2X3kjE/tJwpXgbjCMBpe4rrajFkdK8d6fnKR+0QkW0Sy8/PzvR9AUW9fQfkHdFJ8LG7v3RyxMe5/aq3r1UTfVqlu5SvHDHFsn7OYbHDM9+tx+nwp7v+fe64p/TDeN+f5NnqLKJwEImDkAmiq228C4IBZHRGJA1ALtttNVo71SCk1WSmVoZTKSEtL87HpFI3Mlly1Kq1mIv56qS3X1F8GtbJ0zJIdtltTa/fZrkg++G0Xlmm3qxZuy3PUe2XWNr/aRhRKgbgltRJAGxFpAWA/bJ3Yt7rUmQZgNIClAG4EME8ppURkGoDPReQ1AI0AtAGwIgBtoips0Tb/rzT/1L8FNh8sxOg+6R7r1avpPmO854Q5jltdcx69BG/N3+F3e4jCgd8BQ+uT+CuAmQBiAXyolNooIuMBZCulpgH4AMCnIpID25XFzdqxG0XkawCbAJQAeFApVQoAIvIFgEEAUkUkF8A4pdQH/raXol+TOrY+hA4Nkyt8jpTqCfjgzou91nPtA3Etu+m9ZW6PE0WqgOSSUkpNBzDdpWysbrsIwCiTYycAmGBQfksg2kZVz2ltbsRjQ9uGuCXGCzQF2l0frcCgdvUw2sNIMKJA4ExvijovTt8CAJizOc9LTd+9dGMXv45Pr1vNa53ComLsOnLa0vk2HSjE/K35GDdto8d6Sim8NnsbcvJOWjovkREGDIoa+wrO4PPlex23hFKqmy+EVFE3ZTTFzw/1x4LHBzmVt0qzllrkwHHvuamGv/4rLn1lgWNfKYX0zCyM/dE96cHqfccsPW/B6fN4Y+52XP/2Ekv1iYwwvTlFjQEvzXfaN5p7EQidGtdy2j9y6hzOWxx+e760DHmFRaiXbJ42PffYWaf9zQdtVwWfLN2D8SOd05eM+b48iJwvKUNCnPF3QHugKiwqgVLK75FkVDXxCoOiVlK8+drcgXToRBH2FZz1XlGzao+1q4Kf19lGmCuLU5P2FphPELz6zd8c21ZmpxMZYcCgqBXvZVW9QEmK9/48N19cPt3o2BnjNcF/234EU1eVLyn7w2pbwMizuCbHkNcWArBNDvxxjXlm3NVeZq8TmWHAoKDafLAQWesOhuS54wxmdwfDkNcWuZXd1S/daX/iDeWd5f/83jhh4e0fLMfj36x17M/ZfBgA8N1q62nRS8sUXpm1DX/70nztjezdTNFGFcOAQUF15eu/4sHP3dNlVIY4k0WRAuX67sZpz8Ze1QFjr3JN2Ozs0AnrCzP9tNZ68oMRb/zq2DbLkrvnKHNbUcUwYFBUKC1zv88fHxPcP+8jp4znWLSpXwMigis7NXAqz7yyvWP7kpfnux7mszKD17zlUPmw2a2HjIfQ7rQ4ZJfIFQMGVYr0zCxs2H8iKOdesasArf7pNG8U/VunIibIt6Qm3dTVsLxNPVu69Gev6ehUPqJzQ8e21dX6Wj6ZZfqY68isP/Z2Xs/j1DnvizsR+YIBgyrNVf/5zXulCrjpvaVuZb/lHAnKc+nVreGcR+qF6zpj14vD0aCWbchsYpzzKK3kC3yfF+J6EaFfW2PbYecriE+X7XHar55oGzWfdzIw65ITMWAQBcjwzg2c5je49qHU8hAwDhy3Nix38KsLy8+v3XK7tlsjw7o1Em0Bq+eEuZbOTeQNAwZFtF82HAp1ExxcA4Ivw3qnLNnt8/PZrzBiTfpqTp8rxYpdHBFFgcOZ3iYOHD+LGklxSE4KfHoJCpxvf8/1XimI6lSLd8yrcJ09nRAXg6dGXOi2Ap+R9xbt9Pm5z2qjoKolGE9QHPnWYtNjOdubKoJXGAYW5xxB34nzcMUk9/H10eK295fh77ox/5GqZapzDqfXtI7oCypplvfLNxp3fNvdM6AlRnRp6LFORTXXEhkO7+z7+YtLfVrYkggAA4ah295fDgA46MNY+XDy2fI9GGeQqE5vcc5RfLMqtN/O/XXHhyvcvplf370JXriuM3594tJKacO6XN9mTbetX8Ow/NZe1vNeHS60/V3aR1qZ5Y/yhB3hVBEMGFFozPcbMGXpHu8VK0GdasG7pWe2st6tvZohtYb7SnjB4CmJoJEJ13V2bBfrhsX6skpgrxdsndiOgFGBFCiKFxhUAQwYLv4zd7vT/vbDkbV+gNJ9Eny0eBdKvGRRDfYCP64T6lSQPqkymtfB+JEdvVcMsIvTUypc/9ft5UHCNUPt/QO9ryV+5rytDyMhLgbZTw3BNV2NR0vZDWybhpTqCQDK044Q+YIBw8Wrs7c57V8eAf0YZ8+XOtJA7NcNz3z2p0246LnZHo/t7uVxf5wvKUNhUYnThLJALWr02qytTvv9WqfiDi/rbwdDuwa2SXr/N7iNz8euy3WfyNirRYp2vtYejz1fUoZlWtbZxLgYpNZIRHqq5zU5PrrzYowZfiEA298Gka8YMDRHTp3D4kqY7BUMF479Bd3GzzJ87GSR+2zfyhpqac8hpZ9QtnqvtdTe3rwxL8dp/7qLjPM6VYbdE0fg0ct9Xw72Z4OkjF/e1xu7J45AtYQ4ZD81BDWTjAcytn1qBr5cuc+p7LCXPreYGMHyXeWpzbPWHQzaFR9FJwYMAL9sOIiM5+c4OrsjxYpdBcg9ZkskV1Rsu/V07LRx6mw915nR6ZlZQUkQOHuT+22PrPXByVzr7dt1OMrJO4U9R087zd7WD3VNrZGIn/7aH4DngFhNm6B38pz39/7X7eVfih78/PeI+5un0GLAAHD//0KTTdUfd320Aje9txT9/+WcxO7gCesL+ehVVgryzi6r1R04fhZnzxtnVa0Kdh45jT1HzZMBpqdWxxf39sYLus5yV/Vq2jreL2yQDABo4KEjvl5N58EAS3ZwMSWyjgEjQs3fajyqJtgpvf3lOvu578R5GP3hCr/OOeNvA/w6vrINapfm2D59rsTwtqFen1Z1cYHJ5Dy9By9tjQnXdTIcUmy/Qvns3t4+tpaoHAOGif6tU0PdhAr5fPneUDfBzaujujpG/dgnmwHALi3N9ordBaaLCllxYcNk/xpYyR68tLxDu/BsCY5ZHKnWvVltj4/HxAhu69Uc8bExWP305djy3DAse3Iwru/eGJP+0A2A+4TGVmmRdyuPQocBA8CQC+u5ldkzjnqz9+gZ5BVW7iQos8753/ce83sUUmmZQnpmFl6ZudV7ZRebDhTitEFK7ZHdGuHqrrbZyP+eUz5s+dJXFji2wzHQBYt+JcAlO444jWzzZOr9fS0/R53qCUiKj0WDWkl47aZujvJYl5Tv13QN3WABijwMGACOGnzD+/sV7RzbnkaSXPLyfPR8oXKzgZp1VF7/9hKvx+r7Czo1dv5mfuhEEcZqM8TfnO88Csmb4tIyDH/jV3QcNxOX6QIBYPuQSq/r/Zvs3iqyEpw+LfnP6w7iv7/usnRcoNb3SNaNvKodxImVFH0YMAC0THVP11Bf13FotJpbJFmiuyL508crHdsb9hc61ev94lx8VsFv+vqJZzuPnHaaMCgilnI7eVvD4tS5EpSVKaeFgUb1aFKB1oZW92Z1DMufGnGh12MD0V+z7pkr/D4HVU0MGADaNXAOGDW1hWfsazaXhFnAcB1pZGTaX/s5tv/vy9WO7aU7gzMq5sx551tR87Y43xqz8u14/3HzK4ycvJPoNG4mnv1pI4bo1oTQ9wdECrMssVauwi5smOzUD1RRH911MQDrK/8RAQwYAIDjZ5zHr0+8oQsAoL02i7fLs7Ow5VCh23GvucwKryzrLSx12qVJeQep2drTgeS6utx9n64yrZtXWIT0TPelR9+av8OxvefoaRw9dc6xP+Z7262yKUv34JCuzygS518Um6Rr+ftUa9mDZz58id9t6NuqLgD3ZV6JPAlIwBCRYSKyVURyRCTT4PFEEflKe3y5iKTrHntSK98qIldYPWcgvb1gh9N+/WTbWHX7imbnS8ow7N+/uq1J/YYu75S3nE3BMPsR/z44erbwnAdp8qIdlmcCm30IGqX2nrvFe8f8wJcXoMfzcxz756Lom7C/k6uTApC6PV772zZ734iM+B0wRCQWwFsArgTQAcAtItLBpdrdAI4ppVoDmATgX9qxHQDcDKAjgGEA3haRWIvnDJimKc4L3NhvQcW7pI3O/G6dY9v1Ut4ozUOwtalf0+PjY69y/yd7Ylh7AMCyJwejzMutthemb8HGA+5XVkbMbm0MMBie/OR35kNoTxYVG07kMwoY/70jw1Lbwk2resZXRU8bvF/erB03tEJtiIkRxMUIAwb5JBBXGD0B5CildiqlzgP4EsBIlzojAUzRtqcCGCy2G7kjAXyplDqnlNoFIEc7n5VzBkztCxKc9u0fWMtc7vfbZ9QC7pfy+pQLobbqqSEAjDOpJmpBMCk+Bi+P8rz4DwDDYbJGvl+937B89V7f1ovo/MwsXDj2F8f+IS0/0rkS9yAyuL37cOhIkBgXi3mPDXQrt2eS9YWndcK9KSlTeGu+9atIokAEjMYA9FnQcrUywzpKqRIAJwDU9XCslXMCAETkPhHJFpHs/Hzrawro7XZJzXBEu3e+3CVg6DtyXW9BVdZSod6uCgCgrrYWRBvdYj32DwV753RMjKBFanUszrzM47nqWPwQ+9hkTeoigw96X9jfm9oGH4yBGmYaCi3T3EfmDWiTZlDTWEbzOgEbEtviyekBOQ9Fv0AEDKP/ta6famZ1fC13L1RqslIqQymVkZZm/T+c3pxHB+LbB/pg3mMDcVn7erhaW1fA0zKWoVji8vS5ErT8p/N/bk9J6fT3un/ZcMg2IW+WraPefgupce0LPOYeivFz3WfXiWK+mq4lK2ya4v/IoHAz7mrnW1C+/FtNfaAv1oyt2O0oI5E+dJwqRyACRi6Aprr9JgAOmNURkTgAtQAUeDjWyjkDpn5yEno0T0HLtBr48M6LHR+01Tzk7/lqZcXmK5SWKZw+V1KhTvLxBmsY/M1lHYZhHRsYHvvAZ84JFvW3Mu4f2NL0OQP5QTL1/j4+H3NKy7P045qgvf0hc1e/Fuip3TbUD4MOBft6KkSeBCJgrATQRkRaiEgCbJ3Y01zqTAMwWtu+EcA8ZbtHMg3AzdooqhYA2gBYYfGcQddHG3poZP/xiqUDeeSrNeg4biZaj5nh87FfZe9zK0tPrY4tzw1z7Hfzkm8IsPVf6JMAju6bjv/d3cuwrlHfgSeuAaxb0/L2ZPi4Oh0AHDtzPqrvsX99fx/snjjCaRh0KHyxouqkZqGK8ztgaH0SfwUwE8BmAF8rpTaKyHgRuUar9gGAuiKSA+BRAJnasRsBfA1gE4BfADyolCo1O6e/bfVVB5ekdjd0L59VXNHOxmlrA/9NOVE3mqu1wb1xV/a1M+xEBP3blI9mmnBdJ8f2m/PMU4TM3nQY6ZlZOH6mfJ7Hw0OcA4Z+tT0jz1zdAbsnjjB9/FDhOcdSpBQ8z2dtDnUTKAIEZB6GUmq6UqqtUqqVUmqCVjZWKTVN2y5SSo1SSrVWSvVUSu3UHTtBO66dUmqGp3NWtttdPuwS4mLwwvTNOHGm2DHx6fN7jb+ZB5rr8Md/Dm/v2BYRXJxuSzfRs6Xzt/iEWN/f4lt7NnNs5+TZFvc5bJBg8d5PsgEAL07f4tQWPbNZzYBtpbo7+7UAYJwAEgA2HyxEx3EznY6x/5B/XNfGIPKGM709SIqPxe6JI9C4tm2exhcr9mLyop3oOn6WY1SQlYR52w6fxKo9/i1NuvXQSaf9W3s5B7Mv7+uDteOGIjnJ+crHl/Uxbr64Kf7Yu7nTh3zeyXNYtacAvV6Yi69Xut8SA9xnW7et7/0qx9XrN1/k8zHkn7dv6x7qJlCEYcCw4JeHnRO+NUhOwgEtJbX+m7/ZynFDJy3CDe94zyTryc4j5UN/PxidgRqJzms9x8aI4W2ypZmDLT/HxBu64LlrOzmVnTpXghvesS3p+o9v1xkd5tbPMbKbbeRWuoecR/orJMB9YSUKvoz0FKfbrETe8H+pBTVdvrUfKizCbb1st22u6NTAkXPqCZMP1EBI1c2HGNTO+oS1WkFKX11YVJ5/65ts5zko9vTZ+n4Ru6z/648HBrXCvQOcR2bFW7gSCkQOJXL2/erKmT9E0YEBo4LOa/MwEmJjsEW7XeStQ1ufTM9nus9Tf+c2BMK9U7Id2/bcW6P72G6TXd21EXo0r4M/X9LK7biOjWrhiWHtPfZ1/OeWi7DxWfcU3O0aeE6FQr5b+Hfbcq6NLC4YRlUbA0YF2Se+JcRZ/yd87BvnbKRWV1oDgB35tltSr9/czUvNwPj6z57nTCzfVeDY/l1L/3HirO2qo3a1BHz7QF+fJ9t1aJiMZ67ugKu7NvI4B4YCp2lKNXRslOw1LxkRwIBRYf/6xTYyyNsopJ35pxzbu444pyDpN3Ge5ed7+gdbeu/vfjfO2eTJx9raB3b2TnxPzDLZLtlhnjOrr5/roE//2wDHqClPo6sosA6eKMLCbfn4+zfW0qtT1cWA4adYLeunGfuVAQDsMRhRZbQuhCcVGQrpuuDSv/24Srn1v8tNZ7lbWQCIwk+BtkTxN6vYn0GeMWBYpF/jG7ANHU2Kj4GI4FqDfE4/rN6P3UdO49sA/yfs29p89rkZ/bf1t2/rbpjF1hdPfGucnrxLE+8rARJR5GLAsOiTpbud9rcdPuWYMf3Y0LaOcntOnoe/WoNBryzALxsPBbQddar5ngI7Kd72No/o0hDDO7svaGRmg0HHs+fnCWy/QzvdffVXLaRiJ//lnSyCUgplZQqlZSqq07KQ7+K8VyEAOFxoPsKpYa3yPoHcY2fRKi14t2YqctunWkIc5j02EI0s9F3ouc71qGw/PNgPa/YdR4dGyX6t+0DWffDbLizdcRTrcstXl9z5wvCITiVPgcMrjAA7eOKs1/UFPr27p9N+emYWFueYdyb/b9me8roVXMO6ZVqNCl0B2NNw2K9SKtMFCbHo06oug0Ulem/hTqdgAQDDXl8UotZQuGHAsGj9M9bWHliy46jXOkYL5dz2/nLT+k9pI6RCaeOz5RlxmYOoatl2+JT3SlQlMGBYVDMpHp/d4z3R4DsLdnh83GrgCTf6yYJ5J91vz4V6PQeqOCZyJKsYMHzQr3Uqfn6ov+Fj79+RYekcrmlGokVbTvwiinoMGD7q1LgWRvVwT9j20zrztCBDO9QHANw/sDxVhlngCWeubc68sjyBYKIPM94p/HgahTawbcWWPqbow1FSFfDyqK5oUCsJx3QLBx07U2xav0VadWx7/kqnBHudGvs+Z+GSEP/HdW3zLT2bYeIM24x3zsyObAMMEkXa1QlSAkuKPPxaWEGPDW2H56/t7Ni/p38L07rvLdyJhLgYtw9V15GKj361Br9tP4I8g8WKAOCjOy82LA+VUIycouCol2yefLB2Beb+UHTi//gAqci3/76tnL/Vfbd6P27/YDmue9t57Yz6yYno2Cg5LLLU6iXExqBudX6YRDvX1R6p6mLACJKuFtJkvHBdZ8NyfRZbpRQOF57DjvzwGNqon8wnIpjx8AD8+CBHSEWD/xtcvh77g5e2Qkttzo/+1itVbQwYAdQ0pXwm9as3eU/wp6/vKuP52UjPzMIfJi8DAEcaklCzd3w/N7IjAKBezSR0bVo7lE2iAHnw0vJBGcM7N8SsR2wLVk1fH9j0NhS5GDACaPYjAx3bzSysBSEipqNTjpyyfatboVt3Ihykp1bH7okj8Mc+6aFuCgVYfEz5x0FajUTEcdlccsG/iABKio91pNLQL6x0q7acq5EbDIboGrEve0oULPp8UclMx0IG+CkURFueG4bluwoCMo79heuN+zuIAomzvskTXmEEUVJ8rKVg0dJCQsHNBwsD0SSiCjlzviTUTaAwwIARBibf0cNrne7N6lRCS4ic2efadBg7E6/O2hri1lCoMWCEgdb1anq9FTD4wvqV1BqicvrRef+ZlxPCllA4YMAIQy+yv4KIwpBfAUNEUkRktohs134b3jcRkdFane0iMlpX3kNE1otIjoi8IVruDBEZJSIbRaRMRKylgY0it/Q0H1VFRBQq/l5hZAKYq5RqA2Cutu9ERFIAjAPQC0BPAON0geUdAPcBaKP92Ffp2QDgegBVdqmv/93dy3LKdKJgGdmtkdP+02GwmBeFjr8BYySAKdr2FADXGtS5AsBspVSBUuoYgNkAholIQwDJSqmlyrbS/Cf245VSm5VSVa6HzT6HAwD6t0nFkA7st6DQusRldchPl+3BvoIzIWoNhZq/AaO+UuogAGi/6xnUaQxgn24/VytrrG27lpPOny9piZdu6BLqZlAVNaJLQ7eyjQc4xLuq8jpxT0TmAGhg8NAYi89hlGJVeSj3iYjcB9ttLTRrFn33/p8cfmGom0BVWIJBepD8U+5L9FLV4PUKQyk1RCnVyeDnRwCHtVtL0H7nGZwiF0BT3X4TAAe08iYG5T5RSk1WSmUopTLS0rgyGFEgxcQIfn/6cjSqVb5eBvsxqi5/b0lNA2Af9TQawI8GdWYCGCoidbTO7qEAZmq3sE6KSG9tdNQdJscTUQilVE/AgRPGi3pR1eJvwJgI4HIR2Q7gcm0fIpIhIu8DgFKqAMBzAFZqP+O1MgB4AMD7AHIA7AAwQzv+OhHJBdAHQJaIzPSznURE5Ce/kg8qpY4CGGxQng3gHt3+hwA+NKnXyaD8ewDf+9M2IgqcHs3rYNWeY6FuBoUYZ3oTkVdGwaK0TGFJzpEQtIZChQGDiHxWUlqGjxbvwq3vL8ecTYdD3RyqJAwYROTVDd2dF/raf/wsco/Z1p7fw4l8VQYDBhF5JS6zpga+vAAfL9kNAJi8aAfSM7M4A7wKYMAgIq+mrso1fexwoW0iH9fLiH4MGEQUEDM2HAp1EyjIGDCIKCDOlZR5r0QRjQGDiALmxNniUDeBgogBg4i86pmeAqB8jW8zXZ+dVRnNoRBhwCAirz7+08VITorDor9fGuqmUAgxYBCRV9US4rDumStQLzkJ9w5oEermUIgwYBCRT8aM6GC57vmSMszcyNFT0YIBg4iC5tmfNuLPn65izqkowYBBRH7Z9eJwt7Kvs/chPTMLny3fCwCYNGdbZTeLgoABg4j8Ii55Q4qKS/GPqetcyjhHIxowYBCRzyb9oavpY+2f/sWtLCGOHzXRgO8iEfns0nb1AAD1aiZaqj+qRxPvlSjs+bXiHhFVTbWrJWD3xBGO/QWPD8KgVxaY1o+JEdPHKHLwCoOI/JaeWh2JHm47lZSqSmwNBQsDBhEFhKfkgyVl7PSOBgwYRBR0x04X45lpG1FUXIpXZm5FemYWzjO7bcRhwCCigHjpxi5uZe/e3gOAbR7Gx0t244sVe/Hm/BxgPRYGAAAVZ0lEQVQAQFFJaaW2j/zHgEFEATGyWyO3skvbpzntvzarfALf6XMlQW8TBRYDBhEFRHyM88fJhOs6uZWd1AWJtfuOV0q7KHAYMIgoIPRDZ2/r1Qy39WrucTjtwm35WJ97ojKaRgHCgEFEAdekTjWvdb5YsQ9Xv/lbJbSGAoUBg4gC7qouDUPdBAoCBgwiCphxV9vWykizmDKEIotfAUNEUkRktohs137XMak3WquzXURG68p7iMh6EckRkTdES3spIi+LyBYRWSci34tIbX/aSUSV465+LbB74ggkxcdaPiY9MyuILaJA8vcKIxPAXKVUGwBztX0nIpICYByAXgB6AhinCyzvALgPQBvtZ5hWPhtAJ6VUFwDbADzpZzuJiMhP/gaMkQCmaNtTAFxrUOcKALOVUgVKqWOwBYNhItIQQLJSaqlSSgH4xH68UmqWUso+/m4ZAKa6JIpQE67rFOomUID4GzDqK6UOAoD2u55BncYA9un2c7Wyxtq2a7mrPwGYYdYAEblPRLJFJDs/P9/H5hNRsN3WqzlmP3KJxzrLdx6tpNaQP7wGDBGZIyIbDH5GWnwOo4HYykO5/rnHACgB8JnZyZVSk5VSGUqpjLS0NLNqRBRCberXRHpd21DbxZmXuT3+h8nLKrtJVAFe18NQSg0xe0xEDotIQ6XUQe0WU55BtVwAg3T7TQAs0MqbuJQf0J17NICrAAzWblkRUQSb99ggAFwbI5L5e0tqGgD7qKfRAH40qDMTwFARqaN1dg8FMFO7hXVSRHpro6PusB8vIsMAPAHgGqXUGT/bSERhICZGHMFiULs0DO1QP8QtIl/5GzAmArhcRLYDuFzbh4hkiMj7AKCUKgDwHICV2s94rQwAHgDwPoAcADtQ3lfxJoCaAGaLyBoRedfPdhJRGPn4rp6YfEdGqJtBPvJriVal1FEAgw3KswHco9v/EMCHJvXchlAopVr70y4iigwD26Zh4TYOVokUnOlNRCFzTVf3lOgUvhgwiChk+rVODXUTyAcMGEQUMg1qJWFgW9tweA6GDH8MGEQUUvY+jFNRtgLf1FW5+HHN/lA3I6AYMIgoLCzYGl2d349/sxZ/+3JNqJsRUAwYRBQWHvpiNUpKy0LdDPKAAYOIwsb+42eRnpmFuz9eGeqmkAEGDCIKG7HaTPC5W4yyDFGoMWAQUdiIloFS+hFf+wqiJ7sRAwYRhdRTIy50bJeUlX/QRvIw21V7jjm2KzJSSimFoZMW4ttV5StATF2Vi9fnbA9I+yqKAYOIQuqOPumO7UtfWeDYPltcWvmNCYC1+47jxneXOvYPFRb5fI5zJWXYdvgUHvtmLQAg72QRHv9mLSbN2RawdlYEAwYRhVRCnPHHUFFx5I2YWpd7HCPfWuxUdnF6is/nOXveOVj2nDDXr3YFCgMGEYWl3GORd+//6+x9bmUVmYtRGqa34xgwiCgsZX67PtRN8Nn/lu0NyHmKdfNR0jOzAnLOQGDAIKKQs+eT0isL02/ZevsKzmDijC0oK1NOHd3+Ki4Jz9fOgEFEITeonXvA2HLoZAha4puHv1qDdxfuwKaDhchadzBg5z0fpjPe/VpAiYgoEOJjI+u76wvTN2Pyop2O/aLiUiTGB+41FIdpwIisd4mIolKTOhe4lVVPiA1BS6zRBwvANn/kxNnigJ3fU8B46of1SM/MQllZ5d+2YsAgopAb1K6eW1nfCFpcqaRUYb6HdCa+XDEUl5bhmjcXmz5u71jPP3XOegMDhAGDiMJSnJZXKpwMnbTQcNTS7R8sx/mS8qCw9MnLsHviCEdurKLiUny8eBeOWPiQn7Jkt6W25BUyYBBRFfXUiAvRpM4F2Pr8MADAjA2HQtwid9sOnzJ97Ojp845te6Boqt1qm7HhEJ75aRP+MXWd1+d4PmuzpbaEYhQZO72JKCzcM6Al7hnQ0rF/Q/cmIWyNf2LFFjDqJydh99EzeP9XW5/HyaLA9XNUC0EfD68wiCjs1E9ODLtbUh8t3mW5rmgBY/muAgDlVyZxMeYfue//uhMb9p+w/ByhWM2PVxhEFHbiY2MM5yKcOFuMxLgYJMVX7rfr4tIyPPvTJkt1X7+5G1KqJxg+tnTnUSzJOeLWoa+UMr0VdX33xnh1VFfk5J3C5ZMWOco3HSy02PrA4RUGEYWdhNgYw5FFXZ+dhT+8txSPfrXGkWuqMpZ1vem9pd4raa7q0six3aN5HbfHb31/OQ6dcM5gW2owRDa9bjWsHTsUL93QBSKCOiZBqDIxYBBR2ImLFZSUOn+I2gPD2twT+G71fvT/13ykZ2ah9ZgZyMkL7qzw1XuPW64bq7uV9s/h7Q3rXPn6Iqf9XUdOu9WZ99gg1KoWjzhtUmNdBgwiInfxBlcYu4+6f6ja/fP7DcFuUoW0SK1hWH7sjHPn9z2fZLvViXHpw7H3i+gppfDG3O3Yf/ysH620zq+AISIpIjJbRLZrv92vv2z1Rmt1tovIaF15DxFZLyI5IvKGaP8iIvKciKwTkTUiMktEGhmdl4ii0478U5i7JQ85eaccVxaus6v1Vmidy1Yt23kU2bt9O8Zu14vDse35Kx37t/RsZlrXrC9Db/7WPOw5WrFU7jvyT+O12dvQb+K8Ch3vK3+vMDIBzFVKtQEwV9t3IiIpAMYB6AWgJ4BxusDyDoD7ALTRfoZp5S8rpboopboB+BnAWD/bSUQRxL540pDXFqL1mBkAgDX7rN8W8ubmycucVsXz5tZe5UFBRJwWfbpnQAu/2nLXRyvdyvq0rGvp2BnrA5fw0Ap/A8ZIAFO07SkArjWocwWA2UqpAqXUMQCzAQwTkYYAkpVSS5Vt8d5P7McrpfTd/9UBhGeuXyKqNEYdw8F26lwJ0jOzsGznUdM6+r6W/j6kM/G0ZvlHd11s6RxZERYw6iulDgKA9ts9IQzQGIB+Gapcrayxtu1aDgAQkQkisg/AbeAVBlGVtyPfvA8DABZty/d6DqUUcvLMZ2u7enXWVgDATg/P3ah2En54sB8A4Jpu1u+eF5eaBwyrw4YrOwW814AhInNEZIPBz0iLz2E0+0Z5KLdtKDVGKdUUwGcA/uqhffeJSLaIZOfne/+DIaLI1LlxLY+PT12V6/FxAHhl1lYMeW2h5ec8V+Lc8f7705c7trOfGoJ3b++Bmknx6Na0NrZPuBI3ZTS1fO6vsvch/2Tg8kEVFZd6r+QnrwFDKTVEKdXJ4OdHAIe1W0vQfhula8wFoP9XbALggFbexKDc1ecAbvDQvslKqQylVEZamvsiLEQUHdZ7mQU9ba3Rx4ezt+bv8Ok5XVOI6zuxU2skYlinBo59X9f0ePqHDbh4whyfjpnz6CX4zy0XYfIfe7g9dtBlbkcw+HtLahoA+6in0QB+NKgzE8BQEamjdXYPBTBTu4V1UkR6a6Oj7rAfLyJtdMdfA2CLn+0kIjKVe+yMYyKgXremtf0+d4vU6gCA23qZj6ayqnW9mri6ayO0ruc+XNfTKLJA8Tc1yEQAX4vI3QD2AhgFACKSAeB+pdQ9SqkCEXkOgH0owHillH082wMAPgZwAYAZ2g8ATBSRdgDKAOwBcL+f7SSiCNIitbrTZDZ96vDdE0fgfEkZnvh2HR69vC0+X7EX7yzw7crBVf9/zXecWy8Q/ew/PdQfG/efQK+WdTHhus6G6dH1nhpxoddzXmCQeHDBVvP1OALFr4ChlDoKYLBBeTaAe3T7HwL40KReJ4Ny01tQRBT90momOgWMaWsPoG39Go4kfglxMZj0h24AgCeGta9wwHj6hw04eMJ80ttb83MqdF69Golx6KUbJvv+HRmGE/VyJlyJkjKFxDjvN34a1nJfobBZSjX/GmoBkw8SUdi5s2+602S8x79Zi/6tU1EzKT6gz/Ppsj0eH9fPoG5b33jWtq86mXTex8XGIM6PnIquHfTBwNQgRBR2hndu6HZ7aOvhk17Xk/ht+xFMX38Q6ZlZ+OA353TkvqbP2Hb4pMu+9eG4njSolRSQ8wzr2MBp/7qLGpvUDBxeYRBR2EpOikNhUQkAIP/kOa/DUG//YLlj+7mfN+Hu/uWzsH1Jn5GTdwpDJy3yXjGE+rdJxS8bbasSugbXYOEVBhGFLXuwqGzfr/Y+p8MfL93YxWm/cW33Pglv+vkwqzxQeIVBRGErrWZiQCe3efPr9nwMaJPm83wNX/VqkeLY/vmh/miZVt3nc9RPTgxkkyzhFQYRha23bu3utO/rOtaj3l2CnfmncORUedAxmsNg98hXa31rYAU1r1seINrWr4lqCb5/d6/IMf7iFQYRhS3XFevOnDdOfzGiS0NkrXNPxLdy9zHc9+kqp0R/L17fGafOlRhmiW1dz/yb/nPXus0A8Mvn9/bCT2sPOmW+9dUPD/ZDg+TAdKJbwYBBRGErNsYo5Zw7o2BhV1xa5rTexOHCIqdlVPWW7TReIyMYncp9W6Wibyv/+iECMRPdF7wlRUQRb2iH+qaPuS5O5Lr0qzf/vSOjQm2KRgwYRBTWNo8f5theOWaIYZ2/Xtba8vky0m23uZ65uoPh4/r0589f2wmXewhGVQ0DBhGFNX3epLSaxiOD2jdIdmz//FB/03N9eV9vNKljS6FxZ7/yORprxw51bC/Uratxe+/mvjc4irEPg4giXkJcDF6+sQt6t6yLph5yKl3UzPme/+bxwxAb47zk6pcr9gatnZGOVxhEFBVGZTR1BIvMK9sb1kl0SdZ0QUKs2yilopLgL0QUqRgwiCjsZT81BHMfG2i5/v0DW1X4ufYV2HJOtW9Qs8LniFYMGEQU9lJrJKJVmm/ZYhdnXuZT/Ru6N3HaH2NhXYqqhgGDiKKSa34mbyve3TOghdN+UrwfucajFAMGEUW9G7o3wfiRnmdqx8c6TxLMcJllThwlRURRbN0zQ7H36BnTRYv0WqY63/ISsTbLvCrhFQYRRa3kpHhLwQIAYiymIanKGDCIiMgSBgwiIrKEAYOIiCxhwCAicpFao/JXs4sEDBhERC5+e+LSUDchLHFYLRGR5umrOiC1RgIn7ZlgwCAi0tzdv4X3SlUYb0kREZElDBhERGSJXwFDRFJEZLaIbNd+GyZfEZHRWp3tIjJaV95DRNaLSI6IvCEuc/FF5HERUSLi30rpRETkN3+vMDIBzFVKtQEwV9t3IiIpAMYB6AWgJ4BxusDyDoD7ALTRfobpjmsK4HIAXP6KiCgM+BswRgKYom1PAXCtQZ0rAMxWShUopY4BmA1gmIg0BJCslFqqlFIAPnE5fhKAfwBQfraRiIgCwN+AUV8pdRAAtN/1DOo0BrBPt5+rlTXWtl3LISLXANivlFrrrQEicp+IZItIdn5+vrfqRERUQV6H1YrIHAANDB4aY/E5jFJAKrNyEammnXuolZMrpSYDmAwAGRkZvBohIgoSrwFDKTXE7DEROSwiDZVSB7VbTHkG1XIBDNLtNwGwQCtv4lJ+AEArAC0ArNX6wJsA+F1EeiqlDnlrLxERBYfYug8qeLDIywCOKqUmikgmgBSl1D9c6qQAWAWgu1b0O4AeSqkCEVkJ4CEAywFMB/AfpdR0l+N3A8hQSh2x0J58AHsq+HJSAXh9jijD11w18DVXDf685uZKqTRvlfyd6T0RwNcicjdso5lGAYCIZAC4Xyl1jxYYngOwUjtmvFKqQNt+AMDHAC4AMEP7qTArL9iMiGQrpTL8ef5Iw9dcNfA1Vw2V8Zr9ChhKqaMABhuUZwO4R7f/IYAPTep5XGhXKZXuTxuJiCgwONObiIgsYcAoNznUDQgBvuaqga+5agj6a/ar05uIiKoOXmEQEZElDBgARGSYiGzVkiC65cMKZyLSVETmi8hmEdkoIn/Tyg0TQ4rNG9prXSci3XXnqlCSyFARkVgRWS0iP2v7LURkudb+r0QkQStP1PZztMfTded4UivfKiJX6MrD7m9CRGqLyFQR2aK9332i/X0WkUe0v+sNIvKFiCRF2/ssIh+KSJ6IbNCVBf19NXsOj5RSVfoHQCyAHQBaAkgAsBZAh1C3y4f2NwTQXduuCWAbgA4AXgKQqZVnAviXtj0ctuHLAqA3gOVaeQqAndrvOtp2He2xFQD6aMfMAHBlqF+31q5HAXwO4Gdt/2sAN2vb7wJ4QNv+C4B3te2bAXylbXfQ3u9E2CaL7tD+HsLybwK2fG33aNsJAGpH8/sMW6qgXQAu0L2/d0bb+wzgEtjmqW3QlQX9fTV7Do9tDfV/glD/aP+QM3X7TwJ4MtTt8uP1/Ahblt+tABpqZQ0BbNW23wNwi67+Vu3xWwC8pyt/TytrCGCLrtypXghfZxPYMiRfBuBn7T/DEQBxru8rgJkA+mjbcVo9cX2v7fXC8W8CQLL24Sku5VH7PqM8D12K9r79DFsy06h7nwGkwzlgBP19NXsOTz+8JWWeHDHiaJfgF8E2c94sMaSnZJA+JYkMsX/Dls24TNuvC+C4UqpE29e30/HatMdPaPV9/bcIpZYA8gF8pN2Ge19EqiOK32el1H4Ar8A2KfggbO/bKkT3+2xXGe+rleSxThgwzJMjRhQRqQHgWwAPK6UKPVU1KDNNBumhPGRE5CoAeUqpVfpig6rKy2MR85ph+8bcHcA7SqmLAJyGwfozOhH/mrV76iNhu43UCEB1AFcaVI2m99mbkL5GBgxbxG2q27cnQYwYIhIPW7D4TCn1nVZ8WGwJISHOiSHNXq+ncqMkkaHUD8A1Yssz9iVst6X+DaC2iNizF+jb6Xht2uO1ABTA93+LUMoFkKuUWq7tT4UtgETz+zwEwC6lVL5SqhjAdwD6IrrfZ7vKeF/NnsMUA4Ytx1UbbeRFAmydZdNC3CbLtBEPHwDYrJR6TffQNAD2kRKjYevbsJffoY226A3ghHY5OhPAUBGpo32zGwrb/d2DAE6KSG/tue7QnSsklFJPKqWaKFvamJsBzFNK3QZgPoAbtWqur9n+b3GjVl9p5Tdro2tawLbq4wqE4d+EsmVq3ici7bSiwQA2IYrfZ9huRfUWkWpam+yvOWrfZ53KeF/NnsNcKDu1wuUHtpEH22AbMTEm1O3xse39YbvEXAdgjfYzHLZ7t3MBbNd+p2j1BcBb2mtdD1smYPu5/gQgR/u5S1eeAWCDdsybcOl4DfHrH4TyUVItYfsgyAHwDYBErTxJ28/RHm+pO36M9rq2QjcqKBz/JgB0A5Ctvdc/wDYaJqrfZwDPAtiitetT2EY6RdX7DOAL2PpoimG7Iri7Mt5Xs+fw9MOZ3kREZAlvSRERkSUMGEREZAkDBhERWcKAQUREljBgEBGRJQwYRERkCQMGERFZwoBBRESW/D8GXDPsSH27AQAAAABJRU5ErkJggg==\n", "text/plain": [ "
" ] }, - "metadata": {}, + "metadata": { + "needs_background": "light" + }, "output_type": "display_data" } ], @@ -189,14 +191,14 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 8, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "82.3 ms ± 1.64 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + "83.9 ms ± 1.11 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" ] } ], @@ -213,16 +215,16 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "0.07941211669822223" + "0.08231310210030643" ] }, - "execution_count": 13, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -240,7 +242,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -253,17 +255,17 @@ { "data": { "text/plain": [ - " 200003 function calls in 0.118 seconds\n", + " 200003 function calls in 0.138 seconds\n", "\n", " Ordered by: internal time\n", "\n", " ncalls tottime percall cumtime percall filename:lineno(function)\n", - " 1 0.070 0.070 0.118 0.118 :1(walk)\n", - " 99999 0.039 0.000 0.048 0.000 :1(step)\n", - " 99999 0.008 0.000 0.008 0.000 {method 'random' of '_random.Random' objects}\n", + " 1 0.081 0.081 0.138 0.138 :1(walk)\n", + " 99999 0.047 0.000 0.056 0.000 :1(step)\n", + " 99999 0.009 0.000 0.009 0.000 {method 'random' of '_random.Random' objects}\n", " 1 0.001 0.001 0.001 0.001 {built-in method numpy.core.multiarray.zeros}\n", - " 1 0.000 0.000 0.118 0.118 {built-in method builtins.exec}\n", - " 1 0.000 0.000 0.118 0.118 :2()\n", + " 1 0.000 0.000 0.138 0.138 {built-in method builtins.exec}\n", + " 1 0.000 0.000 0.138 0.138 :2()\n", " 1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}" ] }, @@ -293,11 +295,11 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ - "!pip install line_profiler" + "#!pip install line_profiler" ] }, { @@ -309,7 +311,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 12, "metadata": {}, "outputs": [], "source": [ @@ -325,11 +327,34 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 13, "metadata": {}, "outputs": [], "source": [ - "%load random_walk.py" + "# %load random_walk.py\n", + "import numpy as np\n", + "\n", + "def main():\n", + " n = 100000\n", + " x = walk(n)\n", + "\n", + "def step():\n", + " import random\n", + " return 1. if random.random() > .5 else -1.\n", + "\n", + "def walk(n):\n", + " x = np.zeros(n)\n", + " dx = 1. / n\n", + " for i in range(n - 1):\n", + " x_new = x[i] + dx * step()\n", + " if x_new > 5e-3:\n", + " x[i + 1] = 0.\n", + " else:\n", + " x[i + 1] = x_new\n", + " return x\n", + "\n", + "if __name__==\"__main__\":\n", + " main()\n" ] }, { @@ -342,7 +367,7 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -350,41 +375,41 @@ "text/plain": [ "Timer unit: 1e-06 s\n", "\n", - "Total time: 0.98881 s\n", - "File: \n", + "Total time: 0.760819 s\n", + "File: \n", "Function: main at line 4\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", " 4 def main():\n", - " 5 1 205.0 205.0 0.0 n = 100000\n", - " 6 1 988605.0 988605.0 100.0 x = walk(n)\n", + " 5 1 6.0 6.0 0.0 n = 100000\n", + " 6 1 760813.0 760813.0 100.0 x = walk(n)\n", "\n", - "Total time: 0.169478 s\n", - "File: \n", + "Total time: 0.133749 s\n", + "File: \n", "Function: step at line 8\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", " 8 def step():\n", - " 9 99999 88161.0 0.9 52.0 import random\n", - " 10 99999 81317.0 0.8 48.0 return 1. if random.random() > .5 else -1.\n", + " 9 99999 68856.0 0.7 51.5 import random\n", + " 10 99999 64893.0 0.6 48.5 return 1. if random.random() > .5 else -1.\n", "\n", - "Total time: 0.738541 s\n", - "File: \n", + "Total time: 0.568581 s\n", + "File: \n", "Function: walk at line 12\n", "\n", "Line # Hits Time Per Hit % Time Line Contents\n", "==============================================================\n", " 12 def walk(n):\n", - " 13 1 249.0 249.0 0.0 x = np.zeros(n)\n", - " 14 1 13.0 13.0 0.0 dx = 1. / n\n", - " 15 100000 68894.0 0.7 9.3 for i in range(n - 1):\n", - " 16 99999 494694.0 4.9 67.0 x_new = x[i] + dx * step()\n", - " 17 99999 84339.0 0.8 11.4 if x_new > 5e-3:\n", - " 18 x[i + 1] = 0.\n", + " 13 1 973.0 973.0 0.2 x = np.zeros(n)\n", + " 14 1 3.0 3.0 0.0 dx = 1. / n\n", + " 15 100000 53394.0 0.5 9.4 for i in range(n - 1):\n", + " 16 99999 381885.0 3.8 67.2 x_new = x[i] + dx * step()\n", + " 17 99999 65376.0 0.7 11.5 if x_new > 5e-3:\n", + " 18 1 1.0 1.0 0.0 x[i + 1] = 0.\n", " 19 else:\n", - " 20 99999 90352.0 0.9 12.2 x[i + 1] = x_new\n", + " 20 99998 66949.0 0.7 11.8 x[i + 1] = x_new\n", " 21 1 0.0 0.0 0.0 return x" ] }, @@ -412,7 +437,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -423,7 +448,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -440,7 +465,7 @@ "Name: share, dtype: float64" ] }, - "execution_count": 9, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -451,7 +476,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -464,7 +489,7 @@ "Name: bornCountryCode, dtype: object" ] }, - "execution_count": 10, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -475,7 +500,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 18, "metadata": {}, "outputs": [], "source": [ @@ -491,7 +516,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -507,7 +532,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -604,7 +629,7 @@ "9 Thomson 50.0" ] }, - "execution_count": 14, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -615,7 +640,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -639,16 +664,16 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 22, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 18, + "execution_count": 22, "metadata": {}, "output_type": "execute_result" }, @@ -678,7 +703,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -722,7 +747,7 @@ " name\n", " city\n", " country\n", - " number\n", + " age\n", " \n", " \n", " \n", @@ -748,7 +773,7 @@ " Swedish Gas-Accumulator Co.\n", " Lidingö-Stockholm\n", " Sweden\n", - " 1.0\n", + " 43.0\n", " \n", " \n", " 28\n", @@ -772,7 +797,7 @@ " Uppsala University\n", " Uppsala\n", " Sweden\n", - " 1.0\n", + " 38.0\n", " \n", " \n", " 95\n", @@ -796,7 +821,7 @@ " Royal Institute of Technology\n", " Stockholm\n", " Sweden\n", - " 1.0\n", + " 62.0\n", " \n", " \n", " 124\n", @@ -820,7 +845,7 @@ " Uppsala University\n", " Uppsala\n", " Sweden\n", - " 1.0\n", + " 63.0\n", " \n", " \n", " 168\n", @@ -844,7 +869,7 @@ " Stockholm University\n", " Stockholm\n", " Sweden\n", - " 1.0\n", + " 44.0\n", " \n", " \n", " 187\n", @@ -868,7 +893,7 @@ " Uppsala University\n", " Uppsala\n", " Sweden\n", - " 1.0\n", + " 42.0\n", " \n", " \n", " 217\n", @@ -892,7 +917,7 @@ " Uppsala University\n", " Uppsala\n", " Sweden\n", - " 1.0\n", + " 46.0\n", " \n", " \n", " 320\n", @@ -916,7 +941,7 @@ " Uppsala University\n", " Uppsala\n", " Sweden\n", - " 1.0\n", + " 49.0\n", " \n", " \n", " 378\n", @@ -940,7 +965,7 @@ " Karolinska Institutet, Nobel Medical Institute\n", " Stockholm\n", " Sweden\n", - " 1.0\n", + " 52.0\n", " \n", " \n", " 415\n", @@ -964,7 +989,7 @@ " Karolinska Institutet\n", " Stockholm\n", " Sweden\n", - " 1.0\n", + " 65.0\n", " \n", " \n", " 445\n", @@ -988,7 +1013,7 @@ " Harvard Medical School\n", " Boston, MA\n", " USA\n", - " 1.0\n", + " 57.0\n", " \n", " \n", " 446\n", @@ -1012,7 +1037,7 @@ " Karolinska Institutet\n", " Stockholm\n", " Sweden\n", - " 1.0\n", + " 66.0\n", " \n", " \n", " 447\n", @@ -1036,7 +1061,7 @@ " Karolinska Institutet\n", " Stockholm\n", " Sweden\n", - " 1.0\n", + " 48.0\n", " \n", " \n", " 494\n", @@ -1060,7 +1085,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 64.0\n", " \n", " \n", " 508\n", @@ -1084,7 +1109,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 61.0\n", " \n", " \n", " 518\n", @@ -1108,7 +1133,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 64.0\n", " \n", " \n", " 543\n", @@ -1132,7 +1157,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 56.0\n", " \n", " \n", " 563\n", @@ -1156,7 +1181,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 80.0\n", " \n", " \n", " 598\n", @@ -1180,7 +1205,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 51.0\n", " \n", " \n", " 604\n", @@ -1204,7 +1229,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 57.0\n", " \n", " \n", " 619\n", @@ -1228,7 +1253,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 67.0\n", " \n", " \n", " 634\n", @@ -1252,7 +1277,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 60.0\n", " \n", " \n", " 658\n", @@ -1276,7 +1301,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 74.0\n", " \n", " \n", " 659\n", @@ -1300,7 +1325,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 70.0\n", " \n", " \n", " 692\n", @@ -1324,7 +1349,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 76.0\n", " \n", " \n", " 697\n", @@ -1348,7 +1373,7 @@ " Stockholm School of Economics\n", " Stockholm\n", " Sweden\n", - " 1.0\n", + " 78.0\n", " \n", " \n", " 731\n", @@ -1372,7 +1397,7 @@ " Göteborg University\n", " Gothenburg\n", " Sweden\n", - " 1.0\n", + " 77.0\n", " \n", " \n", " 893\n", @@ -1396,7 +1421,7 @@ " NaN\n", " NaN\n", " NaN\n", - " 1.0\n", + " 80.0\n", " \n", " \n", " 956\n", @@ -1420,7 +1445,7 @@ " Francis Crick Institute\n", " Hertfordshire\n", " United Kingdom\n", - " 1.0\n", + " 77.0\n", " \n", " \n", "\n", @@ -1428,36 +1453,36 @@ "" ], "text/plain": [ - " id firstname surname born died \\\n", - "16 17 Nils Gustaf Dalén 1869-11-30 1937-12-09 \n", - "28 29 Karl Manne Georg Siegbahn 1886-12-03 1978-09-26 \n", - "95 91 Hannes Olof Gösta Alfvén 1908-05-30 1995-04-02 \n", - "124 120 Kai M. Siegbahn 1918-04-20 2007-07-20 \n", - "168 162 Svante August Arrhenius 1859-02-19 1927-10-02 \n", - "187 183 The (Theodor) Svedberg 1884-08-30 1971-02-25 \n", - "217 208 Arne Wilhelm Kaurin Tiselius 1902-08-10 1971-10-29 \n", - "320 305 Allvar Gullstrand 1862-06-05 1930-07-28 \n", - "378 359 Axel Hugo Theodor Theorell 1903-07-06 1982-08-15 \n", - "415 395 Ulf von Euler 1905-02-07 1983-03-09 \n", - "445 424 Torsten N. Wiesel 1924-06-03 0000-00-00 \n", - "446 425 Sune K. Bergström 1916-01-10 2004-08-15 \n", - "447 426 Bengt I. Samuelsson 1934-05-21 0000-00-00 \n", - "494 473 Klas Pontus Arnoldson 1844-10-27 1916-02-20 \n", - "508 485 Karl Hjalmar Branting 1860-11-23 1925-02-24 \n", - "518 495 Lars Olof Jonathan (Nathan) Söderblom 1866-01-15 1931-07-12 \n", - "543 520 Dag Hjalmar Agne Carl Hammarskjöld 1905-07-29 1961-09-18 \n", - "563 543 Alva Myrdal 1902-01-31 1986-02-01 \n", - "598 579 Selma Ottilia Lovisa Lagerlöf 1858-11-20 1940-03-16 \n", - "604 585 Carl Gustaf Verner von Heidenstam 1859-07-06 1940-05-20 \n", - "619 604 Erik Axel Karlfeldt 1864-07-20 1931-04-08 \n", - "634 622 Pär Fabian Lagerkvist 1891-05-23 1974-07-11 \n", - "658 649 Eyvind Johnson 1900-07-29 1976-08-25 \n", - "659 650 Harry Martinson 1904-05-06 1978-02-11 \n", - "692 684 Gunnar Myrdal 1898-12-06 1987-05-17 \n", - "697 689 Bertil Ohlin 1899-04-23 1979-08-03 \n", - "731 722 Arvid Carlsson 1923-01-25 0000-00-00 \n", - "893 868 Tomas Tranströmer 1931-04-15 2015-03-26 \n", - "956 921 Tomas Lindahl 1938-01-28 0000-00-00 \n", + " id firstname surname born died \\\n", + "16 17 Nils Gustaf Dalén 1869-11-30 1937-12-09 \n", + "28 29 Karl Manne Georg Siegbahn 1886-12-03 1978-09-26 \n", + "95 91 Hannes Olof Gösta Alfvén 1908-05-30 1995-04-02 \n", + "124 120 Kai M. Siegbahn 1918-04-20 2007-07-20 \n", + "168 162 Svante August Arrhenius 1859-02-19 1927-10-02 \n", + "187 183 The (Theodor) Svedberg 1884-08-30 1971-02-25 \n", + "217 208 Arne Wilhelm Kaurin Tiselius 1902-08-10 1971-10-29 \n", + "320 305 Allvar Gullstrand 1862-06-05 1930-07-28 \n", + "378 359 Axel Hugo Theodor Theorell 1903-07-06 1982-08-15 \n", + "415 395 Ulf von Euler 1905-02-07 1983-03-09 \n", + "445 424 Torsten N. Wiesel 1924-06-03 0000-00-00 \n", + "446 425 Sune K. Bergström 1916-01-10 2004-08-15 \n", + "447 426 Bengt I. Samuelsson 1934-05-21 0000-00-00 \n", + "494 473 Klas Pontus Arnoldson 1844-10-27 1916-02-20 \n", + "508 485 Karl Hjalmar Branting 1860-11-23 1925-02-24 \n", + "518 495 Lars Olof Jonathan (Nathan) Söderblom 1866-01-15 1931-07-12 \n", + "543 520 Dag Hjalmar Agne Carl Hammarskjöld 1905-07-29 1961-09-18 \n", + "563 543 Alva Myrdal 1902-01-31 1986-02-01 \n", + "598 579 Selma Ottilia Lovisa Lagerlöf 1858-11-20 1940-03-16 \n", + "604 585 Carl Gustaf Verner von Heidenstam 1859-07-06 1940-05-20 \n", + "619 604 Erik Axel Karlfeldt 1864-07-20 1931-04-08 \n", + "634 622 Pär Fabian Lagerkvist 1891-05-23 1974-07-11 \n", + "658 649 Eyvind Johnson 1900-07-29 1976-08-25 \n", + "659 650 Harry Martinson 1904-05-06 1978-02-11 \n", + "692 684 Gunnar Myrdal 1898-12-06 1987-05-17 \n", + "697 689 Bertil Ohlin 1899-04-23 1979-08-03 \n", + "731 722 Arvid Carlsson 1923-01-25 0000-00-00 \n", + "893 868 Tomas Tranströmer 1931-04-15 2015-03-26 \n", + "956 921 Tomas Lindahl 1938-01-28 0000-00-00 \n", "\n", " bornCountry bornCountryCode bornCity \\\n", "16 Sweden SE Stenstorp \n", @@ -1490,36 +1515,36 @@ "893 Sweden SE Stockholm \n", "956 Sweden SE Stockholm \n", "\n", - " diedCountry diedCountryCode ... gender year \\\n", - "16 Sweden SE ... male 1912.0 \n", - "28 Sweden SE ... male 1924.0 \n", - "95 Sweden SE ... male 1970.0 \n", - "124 Sweden SE ... male 1981.0 \n", - "168 Sweden SE ... male 1903.0 \n", - "187 Sweden SE ... male 1926.0 \n", - "217 Sweden SE ... male 1948.0 \n", - "320 Sweden SE ... male 1911.0 \n", - "378 Sweden SE ... male 1955.0 \n", - "415 Sweden SE ... male 1970.0 \n", - "445 NaN NaN ... male 1981.0 \n", - "446 Sweden SE ... male 1982.0 \n", - "447 NaN NaN ... male 1982.0 \n", - "494 Sweden SE ... male 1908.0 \n", - "508 Sweden SE ... male 1921.0 \n", - "518 Sweden SE ... male 1930.0 \n", - "543 Northern Rhodesia (now Zambia) ZM ... male 1961.0 \n", - "563 Sweden SE ... female 1982.0 \n", - "598 Sweden SE ... female 1909.0 \n", - "604 Sweden SE ... male 1916.0 \n", - "619 Sweden SE ... male 1931.0 \n", - "634 Sweden SE ... male 1951.0 \n", - "658 Sweden SE ... male 1974.0 \n", - "659 Sweden SE ... male 1974.0 \n", - "692 Sweden SE ... male 1974.0 \n", - "697 Sweden SE ... male 1977.0 \n", - "731 NaN NaN ... male 2000.0 \n", - "893 Sweden SE ... male 2011.0 \n", - "956 NaN NaN ... male 2015.0 \n", + " diedCountry diedCountryCode ... gender year \\\n", + "16 Sweden SE ... male 1912.0 \n", + "28 Sweden SE ... male 1924.0 \n", + "95 Sweden SE ... male 1970.0 \n", + "124 Sweden SE ... male 1981.0 \n", + "168 Sweden SE ... male 1903.0 \n", + "187 Sweden SE ... male 1926.0 \n", + "217 Sweden SE ... male 1948.0 \n", + "320 Sweden SE ... male 1911.0 \n", + "378 Sweden SE ... male 1955.0 \n", + "415 Sweden SE ... male 1970.0 \n", + "445 NaN NaN ... male 1981.0 \n", + "446 Sweden SE ... male 1982.0 \n", + "447 NaN NaN ... male 1982.0 \n", + "494 Sweden SE ... male 1908.0 \n", + "508 Sweden SE ... male 1921.0 \n", + "518 Sweden SE ... male 1930.0 \n", + "543 Northern Rhodesia (now Zambia) ZM ... male 1961.0 \n", + "563 Sweden SE ... female 1982.0 \n", + "598 Sweden SE ... female 1909.0 \n", + "604 Sweden SE ... male 1916.0 \n", + "619 Sweden SE ... male 1931.0 \n", + "634 Sweden SE ... male 1951.0 \n", + "658 Sweden SE ... male 1974.0 \n", + "659 Sweden SE ... male 1974.0 \n", + "692 Sweden SE ... male 1974.0 \n", + "697 Sweden SE ... male 1977.0 \n", + "731 NaN NaN ... male 2000.0 \n", + "893 Sweden SE ... male 2011.0 \n", + "956 NaN NaN ... male 2015.0 \n", "\n", " category overallMotivation share \\\n", "16 physics NaN 1.0 \n", @@ -1614,41 +1639,41 @@ "893 NaN NaN \n", "956 Francis Crick Institute Hertfordshire \n", "\n", - " country number \n", - "16 Sweden 1.0 \n", - "28 Sweden 1.0 \n", - "95 Sweden 1.0 \n", - "124 Sweden 1.0 \n", - "168 Sweden 1.0 \n", - "187 Sweden 1.0 \n", - "217 Sweden 1.0 \n", - "320 Sweden 1.0 \n", - "378 Sweden 1.0 \n", - "415 Sweden 1.0 \n", - "445 USA 1.0 \n", - "446 Sweden 1.0 \n", - "447 Sweden 1.0 \n", - "494 NaN 1.0 \n", - "508 NaN 1.0 \n", - "518 NaN 1.0 \n", - "543 NaN 1.0 \n", - "563 NaN 1.0 \n", - "598 NaN 1.0 \n", - "604 NaN 1.0 \n", - "619 NaN 1.0 \n", - "634 NaN 1.0 \n", - "658 NaN 1.0 \n", - "659 NaN 1.0 \n", - "692 NaN 1.0 \n", - "697 Sweden 1.0 \n", - "731 Sweden 1.0 \n", - "893 NaN 1.0 \n", - "956 United Kingdom 1.0 \n", + " country age \n", + "16 Sweden 43.0 \n", + "28 Sweden 38.0 \n", + "95 Sweden 62.0 \n", + "124 Sweden 63.0 \n", + "168 Sweden 44.0 \n", + "187 Sweden 42.0 \n", + "217 Sweden 46.0 \n", + "320 Sweden 49.0 \n", + "378 Sweden 52.0 \n", + "415 Sweden 65.0 \n", + "445 USA 57.0 \n", + "446 Sweden 66.0 \n", + "447 Sweden 48.0 \n", + "494 NaN 64.0 \n", + "508 NaN 61.0 \n", + "518 NaN 64.0 \n", + "543 NaN 56.0 \n", + "563 NaN 80.0 \n", + "598 NaN 51.0 \n", + "604 NaN 57.0 \n", + "619 NaN 67.0 \n", + "634 NaN 60.0 \n", + "658 NaN 74.0 \n", + "659 NaN 70.0 \n", + "692 NaN 76.0 \n", + "697 Sweden 78.0 \n", + "731 Sweden 77.0 \n", + "893 NaN 80.0 \n", + "956 United Kingdom 77.0 \n", "\n", "[29 rows x 21 columns]" ] }, - "execution_count": 30, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -1667,16 +1692,23 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 24, "metadata": {}, "outputs": [], "source": [ "nobel[\"number\"] = 1.0" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Pick a few countries to analyze further" + ] + }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 25, "metadata": {}, "outputs": [], "source": [ @@ -1693,7 +1725,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 26, "metadata": {}, "outputs": [ { @@ -1784,7 +1816,7 @@ "United Kingdom 22.0 7.0 6.0 26.0 5.0 22.0" ] }, - "execution_count": 37, + "execution_count": 26, "metadata": {}, "output_type": "execute_result" } @@ -1804,7 +1836,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -1834,7 +1866,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 28, "metadata": {}, "outputs": [], "source": [ @@ -1843,7 +1875,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 29, "metadata": {}, "outputs": [], "source": [ @@ -1871,7 +1903,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 30, "metadata": {}, "outputs": [], "source": [ @@ -1880,7 +1912,32 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 31, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Object `%cpp` not found.\n" + ] + } + ], + "source": [ + "# get help on the cpp magic:\n", + "%cpp?" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Hello World program in C++" + ] + }, + { + "cell_type": "code", + "execution_count": 32, "metadata": {}, "outputs": [ { @@ -1910,40 +1967,34 @@ "### *Exercise 5:* Parallel Python with ipyparallel " ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import module, create client and DirectView object:" + ] + }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 34, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Waiting for connection file: ~/.ipython/profile_default/security/ipcontroller-client.json\n" - ] - }, - { - "ename": "OSError", - "evalue": "Connection file '~/.ipython/profile_default/security/ipcontroller-client.json' not found.\nYou have attempted to connect to an IPython Cluster but no Controller could be found.\nPlease double-check your configuration and ensure that a cluster is running.", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mOSError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mipyparallel\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mipp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mclient\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mipp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mClient\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0mdview\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mclient\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m~/anaconda2/envs/juplab/lib/python3.6/site-packages/ipyparallel/client/client.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, url_file, profile, profile_dir, ipython_dir, context, debug, sshserver, sshkey, password, paramiko, timeout, cluster_id, **extra_args)\u001b[0m\n\u001b[1;32m 411\u001b[0m \u001b[0mno_file_msg\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 412\u001b[0m ])\n\u001b[0;32m--> 413\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mIOError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mmsg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 414\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0murl_file\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 415\u001b[0m \u001b[0;32mraise\u001b[0m \u001b[0mIOError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mno_file_msg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mOSError\u001b[0m: Connection file '~/.ipython/profile_default/security/ipcontroller-client.json' not found.\nYou have attempted to connect to an IPython Cluster but no Controller could be found.\nPlease double-check your configuration and ensure that a cluster is running." - ] - } - ], + "outputs": [], "source": [ "import ipyparallel as ipp\n", "client = ipp.Client()\n", "dview = client[:]" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Import modules, export `random` module to engines:" + ] + }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "metadata": {}, "outputs": [], "source": [ @@ -1954,7 +2005,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "metadata": {}, "outputs": [], "source": [ @@ -1970,17 +2021,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 37, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "3.05 s ± 97.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], "source": [ "%%timeit -n 1\n", "mcpi(int(1e7))" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Function for splitting up the samples and dispatching the chunks to the engines" + ] + }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "metadata": {}, "outputs": [], "source": [ @@ -1998,9 +2064,17 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "1.71 s ± 30.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], "source": [ "%%timeit -n 1\n", "multi_mcpi(dview, int(1e7))" @@ -2010,274 +2084,50 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Lesson 3 - accelerating python" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "import math\n", - "import random\n", - "import numpy as np\n", - "import matplotlib.pyplot as plt\n", - "import seaborn\n", - "%matplotlib inline" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "### Exercise 3.2" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "def primes(kmax): \n", - " p = []\n", - " result = [] \n", - " if kmax > 1000:\n", - " kmax = 1000\n", - " k = 0\n", - " n = 2\n", - " while k < kmax:\n", - " i = 0\n", - " while i < k and n % p[i] != 0:\n", - " i = i + 1\n", - " if i == k:\n", - " p.append(n)\n", - " k = k + 1\n", - " result.append(n)\n", - " n = n + 1\n", - " return result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "t_py = %timeit -o p = primes(100)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%load_ext Cython" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Start with simplest cython" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%%cython -a\n", - "def primes_simplecython(kmax): \n", - " p = []\n", - " result = [] \n", - " if kmax > 1000:\n", - " kmax = 1000\n", - " k = 0\n", - " n = 2\n", - " while k < kmax:\n", - " i = 0\n", - " while i < k and n % p[i] != 0:\n", - " i = i + 1\n", - " if i == k:\n", - " p.append(n)\n", - " k = k + 1\n", - " result.append(n)\n", - " n = n + 1\n", - " return result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "t_cy0 = %timeit -o p = primes_simplecython(100)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Now for proper cythonization. Add annotation (`-a`) if you want!" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "%%cython -a\n", - "def primes_cython(int kmax): # The argument will be converted to int or raise a TypeError.\n", - " cdef int n, k, i # These variables are declared with C types.\n", - " cdef int p[1000] # Another C type\n", - " result = [] # A Python type\n", - " if kmax > 1000:\n", - " kmax = 1000\n", - " k = 0\n", - " n = 2\n", - " while k < kmax:\n", - " i = 0\n", - " while i < k and n % p[i] != 0:\n", - " i = i + 1\n", - " if i == k:\n", - " p[k] = n\n", - " k = k + 1\n", - " result.append(n)\n", - " n = n + 1\n", - " return result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "t_cy = %timeit -o p = primes_cython(100)" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Factor 20 in speedup" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Finally, let's compare with just-in-time compilation with numba" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "from numba import jit, vectorize, float64" + "### *Exercise 6:* Mixing Python and R " ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "metadata": {}, "outputs": [], "source": [ - "@jit\n", - "def primes_jit(kmax): \n", - " p = []\n", - " result = [] \n", - " if kmax > 1000:\n", - " kmax = 1000\n", - " k = 0\n", - " n = 2\n", - " while k < kmax:\n", - " i = 0\n", - " while i < k and n % p[i] != 0:\n", - " i = i + 1\n", - " if i == k:\n", - " p.append(n)\n", - " k = k + 1\n", - " result.append(n)\n", - " n = n + 1\n", - " return result" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "t_jit = %timeit -o p = primes_jit(100)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "print(\" Python: %.3E\\n Simply Cython: %.3E\\n Proper Cython: %.3E\\n Numba-jit: %.3E\"%(t_py.best,t_cy0.best,t_cy.best,t_jit.best))" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Just-in-time compilation comes close to Cython" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Notice that the slowest run took much much longer than the fastest. \n", - "`cache=True` stores the compiled function in file-based cache and avoids re-compilation on re-running\n" + "import pandas as pd\n", + "df = pd.DataFrame({\n", + " 'cups_of_coffee': [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],\n", + " 'productivity': [2, 5, 6, 8, 9, 8, 0, 1, 0, -1]\n", + "})" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 41, "metadata": {}, "outputs": [], "source": [ - "@jit(cache=True)\n", - "def primes_jit2(kmax): \n", - " p = []\n", - " result = [] \n", - " if kmax > 1000:\n", - " kmax = 1000\n", - " k = 0\n", - " n = 2\n", - " while k < kmax:\n", - " i = 0\n", - " while i < k and n % p[i] != 0:\n", - " i = i + 1\n", - " if i == k:\n", - " p.append(n)\n", - " k = k + 1\n", - " result.append(n)\n", - " n = n + 1\n", - " return result" + "%load_ext rpy2.ipython" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 43, "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "image/png": "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7LDDDoFjhEoR4yjWZZm1yqyehl599VXr7sOsed68eYG3rRUqAnFBQAVsXEZK+VQE/ocAajHUwC1btjTXXHNNkoqsWbNm5oknnjCPPvqo2WOPPULHjPVoLIr//e9/m3/84x9JVsUvvvii6dChgzn77LPNwoULQ+dFG1AEooaACtiojYjyowhkQACPOiyC27RpY8MY/uc//3FL7rTTTub+++83zzzzjBW87okS7WDYI5bGp5xyimtwR/NPP/20YUbdt29f88UXX5SII21GESg/Aipgyz8GyoEikBOBF154wRoPnXPOOWbx4sVu+W233dYMHTrUEESiY8eO7vFy7WC0hs8ta7Req2KsPUePHm2F/8CBA2Pj11ouHLXdykBABWxljKP2okIRwFgIoyGMh9577z23lxgX4TKDIDv66KPd8IZugTLvbLfddjYqFIIfNbEQlrV33XWXXTe+5ZZbQnexkHZ1qwiUAwEVsOVAXdtUBHIggHEQRkLMAjEaEsKYCKMijIswMhL/RTkfte3OO+9sHnjgATN+/HjTokULlz3cmwjP+Ne//tUaYsXFpcXtgO4oAj4QUAHrAyQtogiUCgGMgc466yw768NISIgQjRgRYUyEUZEEu5DzUd/us88+ZuzYsYZUeF7jK/xFr7jiCptQ4LHHHouN/3bU8Vb+ooGACthojINyUeUIYPzTp08fawzEbE+IwAUYDTFjxYgIY6I4EynwSIU3YsQI06hRI7crZPUhwhTnn332Wfe47igCcUZABWycR095jz0CzOCuuuoqa/zD7E7C1BEqEPXwzJkzrdEQxkOVQvTtsMMOswEwiAhFTGMhsvycccYZ1mDr+eefl8O6VQRiiYAK2FgOmzIddwQIOUhwCIJEMJvzrkFiFIRxEKnjsBKuVCJu7wknnGBmzZplrrzySpuFRvpKJh9wOPDAA82HH34oh3WrCMQKARWwsRouZbZSEMBQifCG3ljGGAGhHsYoCOOgaiHi4J555pk2vOKFF15oiPcsxDo0KnIlRSCOCIQiYDt16mQNFzR6SxxvCeU5bASYreETKoTRzyOPPGKNgDAGqlYizy4CFtekv/3tb26wCqyo45JNp1rHTvudHoF10h8u7uiiRYtsHFSyd7Ru3dqceuqp5phjjvGVe7K4lo11YP/44499VcNaUD4vNNRW2dLJ8eVdTTMPXyBroSQE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\n" + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ - "%%timeit\n", - "p = primes_jit2(100)" + "%%R -i df -w 6 -h 4 --units cm -r 200\n", + "# the first line says 'import df and make default figure size 5 by 5 inches \n", + "# with resolution 200. You can change the units to px, cm, etc. as you wish.\n", + "library(ggplot2)\n", + "ggplot(df, aes(x=cups_of_coffee, y=productivity)) + geom_line();" ] }, {