目录
在有序数组中查找元素:searchsorted方法和digitize函数
1.pandas的数据结构:Series和DataFrame
@python3.6.6;ubuntu18.04
前言
常用模块为numpy、pandas、matplotlib、scipy
代码编写工具:jupyter
一 numpy模块
1.numpy的数据结构:多维数组ndarray
Numpy最重要的一个特点就是其N维数组对象ndarray,ndarray是一个通用的同构数据多维容器,也就是说其中所有的元组必须是相同类型的,他接收一切序列类型的对象(包括其他数组)。Numpy的ndarray提供了一种将同质数据块(可以是连续或非连续存储的)解释为多维数组对象的方式,数据类型dtype决定了数据的解释方式,比如浮点数、整数、布尔值等
ndarray如此强大的原因部分是因为所有数组对象都是数据块的一个跨度视图(strided view),ndarray不只是一块内存和一个dtype,它还有跨度信息,这使得数组能以各种步幅(step size)在内存中移动,更准确的说,ndarray由以下内容组成:
一个指向数组(一个系统内存块)的指针
一个表示数组形状(shape)的元组,如3*3的数组形状元组为(3,3)
一个跨度元组(stride),其中整数指的是为了前进到当前纬度下一个元素需要跨过的字节数,如3*4*5的foalt64数组,其跨度为(160,40,8)
下图简单地说明了ndarray的内部结构
1.0 ndarray的数据类型(dtype)体系
你可能需要检查数组中所包含的数据是否是整数、浮点数、字符串或python对象,因为浮点数的种类很多,判断dtype是否属于某个大类的工作非常繁琐,但是,dtype都有一个超类(比如np.interger和np.floating),他们可以和np.issubdtype函数结合,调用dtype的mro方法即可查看dtype的所有父类(有些数据类型后面带有下划线,是为了和python的数据类型区别开来)
In [9]: ints=np.ones(10,dtype=np.uint16)
In [10]: floats=np.ones(10,dtype=np.float32)
In [11]: np.issubdtype(ints.dtype,np.integer)#判断数据类型,同python的isinstance
Out[11]: True
In [12]: np.issubdtype(floats.dtype,np.floating)
Out[12]: True
#调用dtype的mro方法即可查看其所有的父类
In [13]: np.float64.mro()
Out[13]:
[numpy.float64,
numpy.floating,
numpy.inexact,
numpy.number,
numpy.generic,
float,
object]
下图简单说明了dtype体系以及父子类关系
1.1 创建数组
import numpy as np
In [15]: np.array([1,2,3])
Out[15]: array([1, 2, 3])#传入列表,产生一维数组
In [16]: np.array([[1,2,3],[4,5,6]])
Out[16]:
array([[1, 2, 3],
[4, 5, 6]])#传入嵌套列表,产生二维数组
#传入一个数组
In [22]: rnd=np.random.randn(12)
In [23]: rnd_re=rnd.reshape(3,4)#reshape,重新构造数组结构
In [24]: rnd
Out[24]:
array([ 0.65986137, 0.59780991, -0.29968381, -0.13900897, -0.91233434,
-1.11650251, 0.10361076, -0.99113903, -0.18876077, -1.07867959,
-1.35017413, -0.02826018])
In [25]: rnd_re
Out[25]:
array([[ 0.65986137, 0.59780991, -0.29968381, -0.13900897],
[-0.91233434, -1.11650251, 0.10361076, -0.99113903],
[-0.18876077, -1.07867959, -1.35017413, -0.02826018]])
In [26]: np.array(rnd_re)
Out[26]:
array([[ 0.65986137, 0.59780991, -0.29968381, -0.13900897],
[-0.91233434, -1.11650251, 0.10361076, -0.99113903],
[-0.18876077, -1.07867959, -1.35017413, -0.02826018]])
1.2 shape和dtype
shape表示各维度大小的元组,tdype用于说明数组数据类型的对象
In [1]: import numpy as np
In [2]: data=np.array([1,2,3])
In [3]: data.shape
Out[3]: (3,)
In [4]: data=np.array([[1,2,3],[4,5,6]])
In [5]: data.shape
Out[5]: (2, 3)
In [6]: data.dtype
Out[6]: dtype('int64')
1.3 empty、zeros、ones
empty创建一个没有任何具体值的数组(应该是无意义的虚数)
zeros创建一个全是0的数组
ones创建一个全是1的数组
In [30]: np.empty((3,3))
Out[30]:
array([[1.96923895e-316, 2.04482388e-316, 3.92581470e+170],
[2.33607195e-301, 5.94613337e-302, 2.29457644e+156],
[3.66137200e-244, 4.10074486e-322, 3.95252517e-322]])
In [32]: np.zeros((3,3))
Out[32]:
array([[0., 0., 0.],
[0., 0., 0.],
[0., 0., 0.]])
In [33]: np.ones((3,3))
Out[33]:
array([[1., 1., 1.],
[1., 1., 1.],
[1., 1., 1.]])
1.4 arange
arange是python内置函数range的数组版
In [34]: np.arange(10)
Out[34]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
1.5 ndarray的数据类型
dtype(数据类型)是一个特殊对象,它含有ndarray将一块内存解释为特定数据类型所需的信息
主要有int64,int32,float64,float32等(不涉及底层工作,很少涉及,不用记)
#数值型dtype的命名方式相同:一个类型名(如int,float),后面跟一个表示各元素位长的数字,如float64
In [36]: np.array([1,2,3]).dtype
Out[36]: dtype('int64')
In [37]: data=np.array([1,2,3],dtype=np.float64)
In [38]: data.dtype
Out[38]: dtype('float64')
1.6 astype
通过astype可以显式的转换数组的数据类型
In [41]: data=np.array(['1','2','3'])
In [42]: data.dtype
Out[42]: dtype('<U1')
In [43]: data.astype(np.float64)#注意:使用astype会创建出一个新的数组(即不改变原始数据)
Out[43]: array([1., 2., 3.])
#astype也可用作调用其他数组的数据类型
In [44]: data1=np.array([1,2,3])
In [45]: data2=np.array(['1','2','3'])
In [46]: data2.astype(data1.dtype)
Out[46]: array([1, 2, 3])
1.7 数组和标量的运算
矢量化(vectorization),数组可以让你不是用循环即可对数据执行批量运算,这通常叫做矢量化
数组和标量之间的运算,会将运算应用到元素级,同样的,大小相等的数组之间的任何运算都会应用到元素级
广播:不同大小数组之间的运算叫做广播
In [47]: data=np.array([[1,2,3],[4,5,6]])
In [49]: data*data
Out[49]:
array([[ 1, 4, 9],
[16, 25, 36]])
In [52]: data*3
Out[52]:
array([[ 3, 6, 9],
[12, 15, 18]])
1.8索引和切片
一维数组很简单,类似python数据类型
In [53]: data=np.array([1,2,3])
In [54]: data[1]
Out[54]: 2
当你将一个标量值赋值给一个切片时,该值会自动传播到整个选区,跟列表最重要的区别在于,数组切片是原始数据的视图,即和数据不会被复制,视图上的任何修改都会直接反映到源数据,若需要得到数组的副本,需要使用data.copy()显式的复制
In [59]: data_arr=np.array([x for x in range(10)])
In [61]: arr_slice=data_arr[5:8]
In [62]: data_arr
Out[62]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [64]: arr_slice
Out[64]: array([5, 6, 7])
In [65]: arr_slice[1]=12345
In [66]: arr_slice
Out[66]: array([ 5, 12345, 7])
In [67]: data_arr
Out[67]:
array([ 0, 1, 2, 3, 4, 5, 12345, 7, 8,
9])
#给数组arr_slice赋值,会改变其源数据data_arr,而列表则不会
In [68]: data_list=[x for x in range(10)]
In [69]: list_slice=data_list[5:8]
In [70]: data_list
Out[70]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
In [71]: list_slice
Out[71]: [5, 6, 7]
In [72]: list_slice[1]=12345
In [73]: list_slice
Out[73]: [5, 12345, 7]
In [74]: data_list
Out[74]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
#使用copy()方法显式的复制源数据,则不会修改源数据
In [75]: data_arr=np.array([x for x in range(10)])
In [76]: data_arr
Out[76]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [77]: arr_slice=data_arr[5:8].copy()
In [78]: arr_slice
Out[78]: array([5, 6, 7])
In [79]: arr_slice=12345
In [80]: arr_slice
Out[80]: 12345
In [81]: data_arr
Out[81]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
二维数组中,索引位置上的元素不再是标量,而是一维数组,因此对各个元素进行递归访问需要的方法不同,其切片有两种方法实现,其中第一种类似嵌套列表的切片
In [84]: data_arr=np.array([[x for x in range(10)],[x for x in range(10,20)]])
In [85]: data_arr
Out[85]:
array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]])
In [86]: data_arr[1][1]
Out[86]: 11
In [87]: data_arr[1,1]
Out[87]: 11
三维数组,切片取值可以理解为三层嵌套列表,同样可以使用两种方法表达
In [90]: data_arr=np.array([[[x for x in range(10)],[x for x in range(10,20)]],[
...: [x for x in range(20,30)],[x for x in range(40,50)]]])
In [91]: data_arr
Out[91]:
array([[[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14, 15, 16, 17, 18, 19]],
[[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49]]])
In [95]: data_arr[1,1,1]
Out[95]: 41
In [92]: data_arr[1]
Out[92]:
array([[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],
[40, 41, 42, 43, 44, 45, 46, 47, 48, 49]])
In [93]: data_arr[1][1]
Out[93]: array([40, 41, 42, 43, 44, 45, 46, 47, 48, 49])
In [94]: data_arr[1][1][1]
Out[94]: 41
布尔型索引
跟算术运算一样,数组的比较运算(如==)也是矢量花的,因此,对数据和字符串的比较运算将会产生一个布尔型数组,布尔型数组的轴长度跟被索引的数组的轴长度一致
In [105]: data=np.array(['a','b','c'])
In [106]: data=='d'
Out[106]: array([False, False, False])
In [107]: data!='d'
Out[107]: array([ True, True, True])
布尔型数组和整数数组混合使用
In [108]: data1=np.array(['a','b','c'])
In [109]: data2=np.array([1,2,3])
In [110]: data_boolean=data1=='a'
In [111]: data_boolean
Out[111]: array([ True, False, False])
In [112]: data2[data_boolean]
Out[112]: array([1])
布尔算术运算符:& |
python中的and和or在numpy中无效
In [108]: data1=np.array(['a','b','c'])
In [109]: data2=np.array([1,2,3])
In [121]: data_boolean=(data1=='a')&(data1=='b')
In [122]: data_boolean
Out[122]: array([False, False, False])
In [123]: data_boolean=(data1=='a')|(data1=='b')
In [124]: data_boolean
Out[124]: array([ True, True, False])
In [125]: data2[data_boolean]
Out[125]: array([1, 2])
花式索引
花式索引(Fancy indexing)是一个Numpy术语,它指利用整数数组进行索引
#子集赋值
In [126]: arr=np.empty((8,4))
In [127]: arr
Out[127]:
array([[1.78873028e-316, 6.92799192e-310, 6.92799191e-310,
6.92799192e-310],
[6.92799191e-310, 6.92799191e-310, 6.92799191e-310,
6.92799191e-310],
[6.92799191e-310, 6.92799191e-310, 6.92799192e-310,
6.92799191e-310],
[6.92799192e-310, 6.92799191e-310, 6.92799191e-310,
6.92799192e-310],
[6.92799191e-310, 6.92799191e-310, 6.92799192e-310,
6.92799192e-310],
[6.92799191e-310, 6.92799191e-310, 5.41734680e-317,
6.92799191e-310],
[6.92799191e-310, 6.92799191e-310, 6.92799191e-310,
6.92799191e-310],
[6.92799192e-310, 6.92799192e-310, 6.92799192e-310,
6.92799191e-310]])
In [128]: for i in range(8):
...: arr[i]=i
...:
In [129]: arr
Out[129]:
array([[0., 0., 0., 0.],
[1., 1., 1., 1.],
[2., 2., 2., 2.],
[3., 3., 3., 3.],
[4., 4., 4., 4.],
[5., 5., 5., 5.],
[6., 6., 6., 6.],
[7., 7., 7., 7.]])
#为了以特定的顺序选取子集,只需要传入一个用于指定顺序的整数列表或ndarray即可
In [130]: arr[[4,3,0,6]]
Out[130]:
array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
#一次传入多个索引数组会有一点特别,他返回一个一维数组,其中的元素对应各个索引元组
In [133]: arr[[1,2,3,4],[5,6,7,0]]#第二个列表表示列的排序,不能超过3
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-133-b97868d57f0c> in <module>()
----> 1 arr[[1,2,3,4],[5,6,7,0]]
IndexError: index 5 is out of bounds for axis 1 with size 4
In [134]: arr[[1,4,5,7],[0,3,1,2]]#返回的是数组的第一列数据,即默认的索引
Out[134]: array([1., 4., 5., 7.])
In [143]: arr[[1,4,5,7]][:,[0,3,1,2]]#前面的列表表示子集,后面列表表示选取的子集的数据排列
Out[143]:
array([[ 4, 7, 5, 6],
[16, 19, 17, 18],
[20, 23, 21, 22],
[28, 31, 29, 30]])
#也可以使用np.ix_函数,它可以将两个一维整数数组转换为一个用于选取方形区域的索引
In [144]: arr[np.ix_([1,4,5,7],[0,3,1,2])]
Out[144]:
array([[ 4, 7, 5, 6],
[16, 19, 17, 18],
[20, 23, 21, 22],
[28, 31, 29, 30]])
数组转置和轴对换
transpose和T
简单转置用T,复杂用transpose
数组转置是重塑的一种特殊形式,它返回的是源数据的视图(不会进行任何复制),数组不仅有transpose方法,还有一个T属性
In [5]: data=np.arange(12).reshape((3,4))
In [6]: data
Out[6]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
In [7]: data.T
Out[7]:
array([[ 0, 4, 8],
[ 1, 5, 9],
[ 2, 6, 10],
[ 3, 7, 11]])
对于高维数组,transpose需要得到一个由轴编号组成的元组,才能对数组进行转置
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]],
[[ 8, 9, 10, 11],
[12, 13, 14, 15]]])
In [12]: arr.transpose((1,0,2))#轴1和轴0互换,轴2不变,原本的顺序是(0,1,2),分别表示总共有三个轴
Out[12]:
array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]],
[[ 4, 5, 6, 7],
[12, 13, 14, 15]]])
矩阵内积
np.dot
In [9]: np.dot(data,data.T)
Out[9]:
array([[ 14, 38, 62],
[ 38, 126, 214],
[ 62, 214, 366]])
通用函数
即(ufunc)既是一种ndarray中的数据执行元素级运算的函数,你可以将其看作简单函数的矢量花包装器
简单函数是指:接受一个或多个标量值,产生一个或多个标量值
sqrt和exp
接收一个变量的ufunc称为一元ufunc,其他如add和maximum称为二元ufunc
In [19]: arr=np.arange(10)
In [20]: np.sqrt(arr)#平方根
Out[20]:
array([0. , 1. , 1.41421356, 1.73205081, 2. ,
2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ])
In [21]: np.exp(arr)#以自然常数e为底数的指数函数,e是一个2.71828....的常数
Out[21]:
array([1.00000000e+00, 2.71828183e+00, 7.38905610e+00, 2.00855369e+01,
5.45981500e+01, 1.48413159e+02, 4.03428793e+02, 1.09663316e+03,
2.98095799e+03, 8.10308393e+03])
add和maximum
In [22]: arr1=np.array([1,2,3])
In [23]: arr2=np.array([4,5,6])
In [24]: np.add(arr1,arr2)#数组1和数组2相加
Out[24]: array([5, 7, 9])
In [29]: arr1=np.array([1,3,5])
In [30]: arr2=np.array([1,2,6])
In [31]: np.maximum(arr1,arr2)#取数组1和数组2对应元素的最大值,组成新数组
Out[31]: array([1, 3, 6])
以下表格是一些常见的通用函数
一元ufunc | |
abs、fabs | 计算整数、浮点数和复数的绝对值,非复数,使用fabs更快 |
sqrt | 计算各元素的平方根,相当于arr**0.5 |
square | 计算各元素的平方,相当于arr**2 |
exp | 计算各元素指数e |
log,log10,log2,log1p | 分别为自然对数(底数为e),底数为10的对数,底数为2的对数,log(1+x) |
sign | 计算各元素的正负号,正为1,0为零,负为-1 |
ceil | 计算各元素的ceiling值,即大于等于该值的最小整数 |
floor | 计算各元素的floor值,即小于等于该值的最小整数 |
rint | 将各元素四舍五入到最接近的整数 |
modf | 将数组的元素的整数和小数部分以两个独立的数组返回 |
isnan | 返回一个哪些值是控制NaN的布尔型数组 |
isfinite,isinf | 是否是有穷(finite),是否是无穷的(isinf),返回一个布尔型数组 |
cos,cosh,sin,sinh,tan,tanh | 普通型和双曲型三角函数 |
arccos,arccosh,arcsin,arcsinh,arctan,arctanh | 反三角函数 |
logical_not | 计算各元素not x的真值,相当于-arr |
二元ufunc | |
add | 将数组中对应元素相加 |
subtract | 将数组中对应元素相减 |
multiply | 数组元素相乘 |
divide,floor_divide | 除法,向下整除(去掉余数) |
power | 对第一个数组中的元素A,根据第二个数组中的元素B,计算A的B次方 |
maximum,fmax | 元素级的最大值计算,fmax忽略NaN值 |
minimum,fimin | 元素级的最小值计算,fmin忽略NaN值 |
mod | 元素级的求模运算(除法的余数) |
copysign | 将第二个数组的值的符号复制给第一个数组中的值 |
greater,greater_equal,less,less_equal,equal,not_equal | 元素级比较运算,最终产生布尔型数组 |
logical_and,logical_or,logical_xor | 元素级逻辑运算,与或非,相当于&、|、^ |
利用数组进行数据处理(矢量化)
Numpy数组使多种数据处理任务可以简单表述为数组表达式(否则需要写循环)
用数组表达式替代循环的做法,通常称作矢量化。
一般来说数组化运算要比纯python的等价运算要快上一两各数量级,尤其是各种数值运算
作为简单的例子,假设我们想要在一组值(网格型)上计算函数sqrt(x^2+y^2)
。np.meshgrid函数接受两个一维数组,并产生两个二维矩阵(对应于两个数组中所有的(x,y)对):
In [48]: points=np.arange(-5,5,0.01)
In [49]: x,y=np.meshgrid(points,points)
In [50]: x
Out[50]:
array([[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
...,
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99],
[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99]])
In [51]: y
Out[51]:
array([[-5. , -5. , -5. , ..., -5. , -5. , -5. ],
[-4.99, -4.99, -4.99, ..., -4.99, -4.99, -4.99],
[-4.98, -4.98, -4.98, ..., -4.98, -4.98, -4.98],
...,
[ 4.97, 4.97, 4.97, ..., 4.97, 4.97, 4.97],
[ 4.98, 4.98, 4.98, ..., 4.98, 4.98, 4.98],
[ 4.99, 4.99, 4.99, ..., 4.99, 4.99, 4.99]])
In [53]: z=np.sqrt(x**2+y**2)
In [54]: z
Out[54]:
array([[7.07106781, 7.06400028, 7.05693985, ..., 7.04988652, 7.05693985,
7.06400028],
[7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,
7.05692568],
[7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,
7.04985815],
...,
[7.04988652, 7.04279774, 7.03571603, ..., 7.0286414 , 7.03571603,
7.04279774],
[7.05693985, 7.04985815, 7.04278354, ..., 7.03571603, 7.04278354,
7.04985815],
[7.06400028, 7.05692568, 7.04985815, ..., 7.04279774, 7.04985815,
7.05692568]])
将条件逻辑表述为数组运算
np.where
np.where函数是三元表达式x if condition else y的矢量化版本。假设我们有一个布尔数组和两个值数组
np.where的第二个和第三个参数不必是数组,它们都可以是标量值。在数据分析工作中,where通常用于根据另一个数组而产生一个新的数组。
In [56]: arr1=np.array([1,2,3,4,5])
In [57]: arr2=np.array([-1,-2,-3,-4,-5])
In [58]: arr3=np.array([True,False,True,False,True])
In [62]: arr=np.array([x if z else y for x,y,z in zip(arr1,arr2,arr3)])
In [63]: arr
Out[63]: array([ 1, -2, 3, -4, 5])
In [64]: arr=np.array(np.where(arr3,arr1,arr2))#np.where返回的是数组
In [65]: arr
Out[65]: array([ 1, -2, 3, -4, 5])
#将np.where用于替换值,如将数组的负数改为2:
In [67]: arr=np.random.randn(10)
In [68]: arr
Out[68]:
array([-0.43310012, -0.78072221, 0.05956466, 0.07686748, -0.29438555,
-0.53863612, 0.96500903, -1.40994316, -1.03975959, 1.83357067])
In [69]: arr_new=np.where(arr<0,2,arr)
In [70]: arr_new
Out[70]:
array([2. , 2. , 0.05956466, 0.07686748, 2. ,
2. , 0.96500903, 2. , 2. , 1.83357067])
数学和统计方法
约简
通过数组上的一组数学函数对整个数组或者某条轴上的数据进行统计计算,如求和sum、平均值mean以及标准差std等聚合计算(aggregation,通常叫做约简(reduction))既可以当做数组的实例方法调用,也可以当做顶级Numpy函数使用
In [4]: arr=np.random.randn(5)#正态分布的随即数据
In [5]: arr
Out[5]: array([-0.11860027, 1.05271905, 0.57255691, -0.49385782, 0.37800909])
In [6]: arr.sum()
Out[6]: 1.3908269625978642
In [7]: np.sum(arr)
Out[7]: 1.3908269625978642
mean和sum
这类函数可以接受一个axis参数,用于计算该轴向上的统计值,最终返回一个少一维的数组
In [9]: arr=np.arange(20).reshape(5,4)
In [10]: arr
Out[10]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
In [14]: arr.sum()#全部元素
Out[14]: 190
In [15]: arr.sum(0)#在数组上一个列表表示一列,axis=0表示的是行,计算的是所有列表每个索引上的和
Out[15]: array([40, 45, 50, 55])
In [16]: arr.sum(1)#数组上一个列表表示一列,axis=1表示的是列,计算的一个列表的和
Out[16]: array([ 6, 22, 38, 54, 70])
cumsum和cumprod
累计和,累计积这类方法则不聚合,而是产生一个由中间结果组成的数组
In [17]: arr
Out[17]:
array([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11],
[12, 13, 14, 15],
[16, 17, 18, 19]])
In [18]: arr.cumsum(axis=1)#列表内的累计和
Out[18]:
array([[ 0, 1, 3, 6],
[ 4, 9, 15, 22],
[ 8, 17, 27, 38],
[12, 25, 39, 54],
[16, 33, 51, 70]])
In [19]: arr.cumprod(axis=1)#列表内的累计积
Out[19]:
array([[ 0, 0, 0, 0],
[ 4, 20, 120, 840],
[ 8, 72, 720, 7920],
[ 12, 156, 2184, 32760],
[ 16, 272, 4896, 93024]])
基本数组统计方法
sum | 全部或某轴向的元素求和,零长度的数组的sum为0 |
mean | 全部或某轴向的元素平均值,零长度的数组的mean为NaN |
std、var | 分别为标准差和方差,自由度可调(默认为n) |
min、max | 全部或某轴向上的最大值和最小值 |
argmin、argmax | 全部或某轴向上的最大最小值的索引 |
cumsum | 全部或某轴向上的累计和 |
cumprod | 全部或某轴向上的累计积 |
用于布尔型数组的方法
在使用统计方法时,布尔值会强制转换为1(True)和0(Flase),因此sum经常被用来对布尔型数组中True值的计数
In [28]: arr=np.random.randn(100)
In [29]: (arr>0).sum()
Out[29]: 52
any和all
any用于判断存在一个或多个,all用于判断全部都是
In [28]: arr=np.random.randn(100)
In [30]: (arr>0).any()
Out[30]: True
In [31]: (arr>0).all()
Out[31]: False
排序sort
arr.sort和np.sort
通过arr.sort方法就地排序(直接改变源数据),np.sort()返回的是数组的已排序副本(即不修改源数据),可以对全部元素或者某轴向上的元素进行排序
In [46]: arr=np.random.randn(12).reshape(4,3)
In [47]: arr
Out[47]:
array([[ 5.82831352e-02, -7.74374388e-01, 1.47850625e+00],
[ 8.30603959e-01, -5.74236357e-01, -4.13521434e-01],
[ 8.70914589e-04, -5.46720474e-01, -5.41121958e-01],
[-7.03866197e-01, 1.95273830e+00, -5.85538385e-01]])
In [48]: arr.sort()#默认axis=1,在列上排序
In [49]: arr
Out[49]:
array([[-7.74374388e-01, 5.82831352e-02, 1.47850625e+00],
[-5.74236357e-01, -4.13521434e-01, 8.30603959e-01],
[-5.46720474e-01, -5.41121958e-01, 8.70914589e-04],
[-7.03866197e-01, -5.85538385e-01, 1.95273830e+00]])
In [50]: arr.sort(0)#行上排序,会改变列表的值
In [51]: arr
Out[51]:
array([[-7.74374388e-01, -5.85538385e-01, 8.70914589e-04],
[-7.03866197e-01, -5.41121958e-01, 8.30603959e-01],
[-5.74236357e-01, -4.13521434e-01, 1.47850625e+00],
[-5.46720474e-01, 5.82831352e-02, 1.95273830e+00]])
np.sort(arr)
In [52]: arr=np.random.randn(12).reshape(4,3)
In [53]: arr
Out[53]:
array([[-1.0651435 , -0.70624382, 0.05124272],
[ 0.69190929, 1.03548097, 0.64937742],
[ 1.54626701, -0.08302486, 0.39043255],
[-1.03014956, -0.12934306, 1.47813622]])
In [54]: np.sort(arr)
Out[54]:
array([[-1.0651435 , -0.70624382, 0.05124272],
[ 0.64937742, 0.69190929, 1.03548097],
[-0.08302486, 0.39043255, 1.54626701],
[-1.03014956, -0.12934306, 1.47813622]])
In [55]: arr
Out[55]:
array([[-1.0651435 , -0.70624382, 0.05124272],
[ 0.69190929, 1.03548097, 0.64937742],
[ 1.54626701, -0.08302486, 0.39043255],
[-1.03014956, -0.12934306, 1.47813622]])
唯一化和其他集合逻辑
np.unique
numpy提供了一些针对一维ndarray的基本集合运算,最常用的时np.unique,它用于找出数组中的唯一值并返回已排序的结果
In [61]: arr=np.array([1,1,2,3,4,5,2,3,4,5,6])
In [62]: np.unique(arr)
Out[62]: array([1, 2, 3, 4, 5, 6])
np.in1d
用于测试一个数组中的值在另一个数组中的成员资格,返回一个布尔型数组,第一个参数为源数据,验证第二个参数在源数据中的成员资格
In [68]: arr1=np.array([1,2,3,4,5])
In [69]: arr2=np.array([1,2,3,4,5,6])
In [70]: np.in1d(arr1,arr2)
Out[70]: array([ True, True, True, True, True])
In [71]: np.in1d(arr1,[1,2
...: ])
Out[71]: array([ True, True, False, False, False])
数组中的集合运算
unique() | 计算x中的唯一元素(去重),并返回有序结果 |
intersect1d(x,y) | 计算x,y的公共元素,并返回有序结果 |
union1d(x,y) | 计算x,y的并集,并返回有序结果 |
in1d(x,y) | 得到一个表示'y元素是否在x中'的布尔型数组,数组长度等于x |
setdiff1d(x,y) | 集合的差,即元素在x中且不在y中 |
setxor1d(x,y) | 集合的对称差,即存在于一个数组中,但不同时存在于两个数组中的元素,即'异或' |