{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# ufunc 对象" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Numpy** 有两种基本对象:`ndarray (N-dimensional array object)` 和 `ufunc (universal function object)`。`ndarray` 是存储单一数据类型的多维数组,而 `ufunc` 则是能够对数组进行处理的函数。\n", "\n", "例如,我们之前所接触到的二元操作符对应的 **Numpy** 函数,如 `add`,就是一种 `ufunc` 对象,它可以作用于数组的每个元素。" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([2, 4, 6])" ] }, "execution_count": 2, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([0,1,2])\n", "b = np.array([2,3,4])\n", "\n", "np.add(a, b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "查看支持的方法:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "['__call__',\n", " '__class__',\n", " '__delattr__',\n", " '__doc__',\n", " '__format__',\n", " '__getattribute__',\n", " '__hash__',\n", " '__init__',\n", " '__name__',\n", " '__new__',\n", " '__reduce__',\n", " '__reduce_ex__',\n", " '__repr__',\n", " '__setattr__',\n", " '__sizeof__',\n", " '__str__',\n", " '__subclasshook__',\n", " 'accumulate',\n", " 'at',\n", " 'identity',\n", " 'nargs',\n", " 'nin',\n", " 'nout',\n", " 'ntypes',\n", " 'outer',\n", " 'reduce',\n", " 'reduceat',\n", " 'signature',\n", " 'types']" ] }, "execution_count": 3, "metadata": {}, "output_type": "execute_result" } ], "source": [ "dir(np.add)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "除此之外,大部分能够作用于数组的数学函数如三角函数等,都是 `ufunc` 对象。\n", "\n", "特别地,对于二元操作符所对应的 `ufunc` 对象,支持以下方法:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## reduce 方法" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " op.reduce(a)\n", "\n", "将`op`沿着某个轴应用,使得数组 `a` 的维数降低一维。\n", "\n", "add 作用到一维数组上相当于求和:\n", "\n", "$$\n", "\\begin{align}\n", "y & = add.recuce(a) \\\\\n", "& = a[0] + a[1] + ... + a[N-1] \\\\\n", "& = \\sum_{n=0}^{N-1} a[n]\n", "\\end{align}\n", "$$" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "10" ] }, "execution_count": 4, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([1,2,3,4])\n", "\n", "np.add.reduce(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "多维数组默认只按照第一维进行运算:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([5, 7, 9])" ] }, "execution_count": 5, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([[1,2,3],[4,5,6]])\n", "\n", "np.add.reduce(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "指定维度:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 6, 15])" ] }, "execution_count": 6, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.add.reduce(a, 1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "作用于字符串:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "'abcdef'" ] }, "execution_count": 7, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array(['ab', 'cd', 'ef'], np.object)\n", "\n", "np.add.reduce(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "逻辑运算:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "False" ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([1,1,0,1])\n", "\n", "np.logical_and.reduce(a)" ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "True" ] }, "execution_count": 9, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.logical_or.reduce(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## accumulate 方法" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " op.accumulate(a)\n", "\n", "`accumulate` 可以看成保存 `reduce` 每一步的结果所形成的数组。\n", "\n", "$$\n", "\\begin{align}\n", "y & = add.accumulate(a) \\\\\n", "& = \\left[\\sum_{n=0}^{0} a[n], \\sum_{n=0}^{1} a[n], ..., \\sum_{n=0}^{N-1} a[n]\\right]\n", "\\end{align}\n", "$$\n", "\n", "与之前类似:" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ 1, 3, 6, 10])" ] }, "execution_count": 10, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([1,2,3,4])\n", "\n", "np.add.accumulate(a)" ] }, { "cell_type": "code", "execution_count": 11, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array(['ab', 'abcd', 'abcdef'], dtype=object)" ] }, "execution_count": 11, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array(['ab', 'cd', 'ef'], np.object)\n", "\n", "np.add.accumulate(a)" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ True, True, False, False], dtype=bool)" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([1,1,0,1])\n", "\n", "np.logical_and.accumulate(a)" ] }, { "cell_type": "code", "execution_count": 13, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([ True, True, True, True], dtype=bool)" ] }, "execution_count": 13, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.logical_or.accumulate(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## reduceat 方法" ] }, { "cell_type": "markdown", "metadata": { "collapsed": true }, "source": [ " op.reduceat(a, indices)\n", "\n", "`reduceat` 方法将操作符运用到指定的下标上,返回一个与 `indices` 大小相同的数组:\n", "\n", "$$\n", "\\begin{align}\n", "y & = add.reduceat(a, indices) \\\\\n", "& = \\left[\\sum_{n=indice[0]}^{indice[1]-1} a[n], \\sum_{n=indice[1]}^{indice[2]-1} a[n], ..., \\sum_{n=indice[-1]}^{N-1} a[n]\\right]\n", "\\end{align}\n", "$$" ] }, { "cell_type": "code", "execution_count": 14, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([60, 90])" ] }, "execution_count": 14, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([0, 10, 20, 30, 40, 50])\n", "indices = np.array([1,4])\n", "\n", "np.add.reduceat(a, indices)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "这里,`indices` 为 `[1, 4]`,所以 `60` 表示从下标1(包括)加到下标4(不包括)的结果,`90` 表示从下标4(包括)加到结尾的结果。" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## outer 方法" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " op.outer(a, b)\n", "\n", "对于 `a` 中每个元素,将 `op` 运用到它和 `b` 的每一个元素上所得到的结果:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2, 3],\n", " [2, 3, 4]])" ] }, "execution_count": 15, "metadata": {}, "output_type": "execute_result" } ], "source": [ "a = np.array([0,1])\n", "b = np.array([1,2,3])\n", "\n", "np.add.outer(a, b)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "注意有顺序的区别:" ] }, { "cell_type": "code", "execution_count": 16, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "array([[1, 2],\n", " [2, 3],\n", " [3, 4]])" ] }, "execution_count": 16, "metadata": {}, "output_type": "execute_result" } ], "source": [ "np.add.outer(b, a)" ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }