{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "In this post, I would like to discuss something that struck me a couple of months ago: why doesn't Python have a builtin argmax function? The [argmax points of a function](https://en.wikipedia.org/wiki/Arg_max) are the ones that maximize the value of the function over a given domain." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# The beginner's point of view " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When I first started programming in Python, I quickly learned about the `max` keyword, that allows to easily extract the biggest item of an iterable. For example:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "l = [1, 3, 75, 4, 9]" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "75" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "max(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Come in Numpy " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "After my beginner years, I moved on to numerical computing with Python and Numpy. Numpy features both a `max` and an `argmax` function:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.max" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.argmax" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The basic way to use `argmax` is like this:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "2" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.argmax(l)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This means that the biggest value found in the list `l` has index 2:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "75" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "l[2]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Why argmax is useful: an example " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "At that point in my learning history, I realized that the argmax behaviour is very often useful. In numerical computing for example, you might want to know where the minimum value of a function lies:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": true }, "outputs": [], "source": [ "x = np.linspace(0, 1)\n", "y = -(x - 0.4)**2" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import matplotlib.pyplot as plt\n", "plt.style.use('ggplot')\n", "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "(-0.4, 0.1)" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAEECAYAAADHzyg1AAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzt3Xt8XHWd//HXTNK0tkxvaZOSNilsUaisoj5+i6yuEnRd\nLqJld5sv4AXSKilQLpKCXBa24AORCg20tF0IlxTUfZRvKyxVQcXFrD/loYILygMKQoFO00LSpk1v\nobTNnP1jpjNJ5kwzmTMzZ2byfj4ePszMfOecbz+cOZ9zvrcTcBwHERERgKDfFRARkcKhpCAiInFK\nCiIiEqekICIicUoKIiISp6QgIiJx5dnYiDHmDOBuoknmQWvtkkGfHw+0AZ8AbrDWtmRjvyIikl2e\n7xSMMUFgBXA6cCJwvjHmhEHFuoHLgTsy2H691zqWCsUiSnFIUCwSFIsEL7HIRvPRycDr1tpN1tqD\nwBpgTv8C1trt1to/AYcy2H699yqWjHq/K1Ag6v2uQAGp97sCBaTe7woUkPpMv5iNpDAd2NzvdUfs\nPRERKTLqaBYRkbhsdDRvAer6vZ4Rey8jsbaw+sOvrbWLgcWZbq+UWGtBsVAc+lEsEhSLBGstxpj+\nb7Vba9vT+W42ksJzwHHGmJnAO8B5wPlHKB840sZiFW/v99birVu3eqxiaQiFQuzZs8fvavhOcUhQ\nLBIUi4SamhqstTdn8t1ANlZJjQ1JXUZiSOrtxpgFgGOtbTXGVAPPAyEgAuwFPmyt3ZvG5h0lhSgd\n9FGKQ4JikaBYJNTU1MAQF+CpZCUp5JiSQowO+ijFIUGxSFAsErwkBXU0i4hInJKCiIjEKSmIiEic\nkoKIiMQpKYiISJySgoiIxCkpiIhInJKCiIjEKSmIiEickoKIiMQpKYiISJySgoiIxCkpiIhInJKC\niIjEKSmIiEickoKIiMQpKYiISJySgoiIxCkpiIhInJKCiIjEKSmIiEickoKIiMQpKYiISJySgoiI\nxCkpiIhInJKCiIjEKSmIiEickoKIiMQpKYiISJySgoiIxCkpiIhInJKCiIjEKSmIiEickoKIiMQp\nKYiISJySgoiIxJVnYyPGmDOAu4kmmQettUtcyiwHzgT2AY3W2hezsW8REckez0nBGBMEVgCfB7YC\nzxljnrDWvtqvzJnALGvtB40xnwTuBU7xum8pbZvDYezK5UR2dhOcVIlZeAW1dXVDfiYimcvGncLJ\n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\nwF0uqQAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.plot(x, y, '-o')\n", "plt.ylim(-0.4, 0.1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Using argmax, this is easy: find the index of the maximum value in the `y` values and then use that index with the `x` array:" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.4081632653061224" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "index = np.argmax(y)\n", "x[index]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This however, leads me back to my original question: why doesn't this exist in pure Python? This is often useful for finding the best parameters to functions that are not necessarily numerical!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# It doesn't go by the name argmax... but max! " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It turns how that it exists, and that I just didn't see it all these years, as it was hidden in plain sight!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you read the [documentation](https://docs.python.org/3/library/functions.html#max) about the builtin `max` function, you'll see it accepts an optional argument called `key`:\n", "\n", "> The key argument specifies a one-argument ordering function like that used for list.sort()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If you specify a key function, it will evaluate the function using the values in the list and return the object that maximizes the provided function. This seems like no big deal but actually makes the function work like argmax! \n", "\n", "\n", "Let's see it in action. I'll define `f` as the function I used to create the curve shown above, a negative looking parabola." ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": true }, "outputs": [], "source": [ "f = lambda x: -(x - 0.4)**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, I can use the optional keyword `key`:" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "0.4081632653061224" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "max(x, key=f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is exactly the same result as above using Numpy's argmax. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Conclusion " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So, to wrap this article up:\n", "\n", "- there is an argmax function builtin with Python, but it doesn't say it's true name\n", "- you can use it with the `key` optional argument\n", "- the likely reason this is so is that it makes it very close in functionality to the `list.sort` function, that also accepts an optional `key` argument" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This post was entirely written using the IPython notebook. Its content is BSD-licensed. You can see a static view or download this notebook with the help of nbviewer at [20160524_PythonMissingArgmax.ipynb](http://nbviewer.ipython.org/urls/raw.github.com/flothesof/posts/master/20160524_PythonMissingArgmax.ipynb)." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.5.1" } }, "nbformat": 4, "nbformat_minor": 0 }