Numpy的ndarry
Numpy的ndarry:一种多维数组对象
Numpy最重要的一个特点就是其N维数组对象(即ndarry),该对象是一个快速而灵活的大数据集容器。你可以利用这种数组对整块数据执行一些数学运算,其语法跟标量元素之间的运算一样:
In [52]: data=np.array([[1,2,3],[4,5,6]]) In [53]: data
Out[53]:
array([[1, 2, 3],
[4, 5, 6]]) In [54]: data*10
Out[54]:
array([[10, 20, 30],
[40, 50, 60]]) In [55]: data+data
Out[55]:
array([[ 2, 4, 6],
[ 8, 10, 12]])
ndarry是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。每个数组都有一个shape(一个表示维度大小的元组)和一个dtype(一个说明数组数据类型的对象):
In [56]: data.shape
Out[56]: (2, 3) In [57]: data.dtype
Out[57]: dtype('int32')
创建ndarry
创建数组的最简单办法就是使用array函数。它接受一切序列型对象(包括其他数组),然后产生一个新的含有传入数据的Numpy数组。
In [59]: data1=[6,7.8,8,0,True] In [60]: arr1=np.array(data1) In [61]: arr1
Out[61]: array([6. , 7.8, 8. , 0. , 1. ])
嵌套序列(比如由一组等长列表组成的列表)将会被转换为一个多维数组:
In [62]: data2=[[1,2,3,4],[5,6,7,8]] In [63]: arr2=np.array(data2) In [64]: arr2
Out[64]:
array([[1, 2, 3, 4],
[5, 6, 7, 8]]) In [65]: arr2.ndim
Out[65]: 2 In [66]: arr2.shape
Out[66]: (2, 4)
除非显示说明,np.array会尝试为新建的这个数组推断出一个较为合适的数据类型。数据类型会保存在一个特殊的dtype对象中。
In [69]: arr1.dtype
Out[69]: dtype('float64') In [70]: arr2.dtype
Out[70]: dtype('int32')
除np.array外,还有一些函数也可以新建数组。例如,zeros和ones分别可以创建指定长度或形状的全0或全1数组。empty可以创建一个没有任何具体指的数组。要用这些方法创建多维数组,只需要传入一个表示形状的元组即可:
In [73]: np.zeros(10)
Out[73]: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.]) In [74]: np.zeros((3,6))
Out[74]:
array([[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.]]) In [75]: np.empty((2,3,2))
Out[75]:
array([[[6.23042070e-307, 4.67296746e-307],
[1.69121096e-306, 8.90101523e-307],
[1.55762979e-307, 1.78022342e-306]], [[8.06635958e-308, 1.86921415e-306],
[1.27946330e-307, 1.11262266e-307],
[1.00133162e-307, 1.22387381e-307]]])
注意:认为np.empty会返回全0数组的想法是不安全的。很多情况下,它返回的都是一些未初始化的垃圾值。
arange是python内置韩素华range的数组版:
In [76]: np.arange(15)
Out[76]: array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14])
数组创建函数:
array:将输入数据(列表 元组 数组或其他序列类型)转换未ndarry。要么推断出dtype,要么显示指定dtype。默认执行复制输入数据。
asarry:将输入转换未ndarry,如果输入本身就是一个ndarry就不进行复制。
arange:类似与内置的range,返回的是一个ndarry而不是列表
ones丶ones_like:根据指定的形状和dtype创建一个全1数组。ones_like以另外一个数组为参数,并根据其形状和dtype创建一个全1数组。
zeros丶zeros_like:类似ones丶ones_like,不过产生的是全0数组。
empty丶empty:创建新数组,只分配内存空间但不填充任何值。
eyp丶identity:创建一个正方的N x N单位矩阵(对角线为1,其余为0)
ndarry的数据类型
dtype是一个特殊的对象,它含有ndarry将一块内存解释为特定数据类型所需的信息:
它包含的数据类型:int8丶uint8丶int16丶unit16丶int32丶uint32丶int64丶uint64丶float16丶float32丶float64丶float128丶bool等
可以通过ndarry的astype方法显式地转换其dtype:
In [78]: arr=np.array([1,2,3,4,5]) In [79]: arr.dtype
Out[79]: dtype('int32') In [80]: float_arr=arr.astype(np.float64) In [81]: float_arr.dtype
Out[81]: dtype('float64')
数组和标量之间的运算
数组很重要,因为你使它不用编写循环即可对数组执行批量运算,这通常就叫矢量化。
In [83]: arr=np.array([[1,2,3],[4,5,6]]) In [84]: arr
Out[84]:
array([[1, 2, 3],
[4, 5, 6]]) In [85]: arr*arr
Out[85]:
array([[ 1, 4, 9],
[16, 25, 36]]) In [86]: arr -arr
Out[86]:
array([[0, 0, 0],
[0, 0, 0]]) In [87]: 1/arr
Out[87]:
array([[1. , 0.5 , 0.33333333],
[0.25 , 0.2 , 0.16666667]]) In [88]: arr ** 2
Out[88]:
array([[ 1, 4, 9],
[16, 25, 36]], dtype=int32)
基本的索引和切片
一维数组选取数据子集或单个元素的方式跟python列表功能差不多:
In [90]: arr
Out[90]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) In [91]: arr[5]
Out[91]: 5 In [92]: arr[5:8]
Out[92]: array([5, 6, 7])
Out[94]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
当in将一个标量值赋值给一个切片时(如arr[5:8]=12),该值会自动传播到整个选区,也就是广播。跟列表最重要的区别在于,数组切片是原始数组的视图。这意味着数据不会被复制,视图上任何修改都会直接反映到源数组上:
In [94]: arr
Out[94]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9]) In [95]: arr_slice=arr[5:8] In [96]: arr_slice[1]
Out[96]: 12 In [97]: arr_slice[1]=12345 In [98]: arr
Out[98]:
array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8,
9]) In [99]: arr_slice[:]=64 In [100]: arr
Out[100]: array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])
由于Numpy的设计目的是处理大数据,可以想象下加入numpy坚持将数据复制来复制去的话会产生什么样的性能和内存问题。如果你想要得到的是ndarry切片的一份副本而非视图,就需要显式的进行复制操作,例如arr[5:8].copy() 。
在一个二维数组中,各索引位置上的元素不再是标量而是一维数组:
In [101]: arr2=np.array([[1,2,3],[4,5,6],[7,8,9]]) In [102]: arr2[2]
Out[102]: array([7, 8, 9])
因此,可以对多个元素进行递归访问,,也可以传入一个逗号隔开的索引列表来选取单个元素,两种方式是等价的:
In [109]: arr2[0][2]
Out[109]: 3 In [110]: arr2[0,2]
Out[110]: 3
在多维数组中,如果省略了后面的索引,则返回对象是一个维度低一点的ndarry。
In [111]: arr3d=np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]]) In [112]: arr3d
Out[112]:
array([[[ 1, 2, 3],
[ 4, 5, 6]], [[ 7, 8, 9],
[10, 11, 12]]])
arr3d是一个2x3的数组
In [113]: arr3d[0]
Out[113]:
array([[1, 2, 3],
[4, 5, 6]])
标量值和数组都可以被赋值给arr3d[0]:
In [114]: old_values=arr3d[0].copy() In [115]: arr3d[0]=42 In [116]: arr3d
Out[116]:
array([[[42, 42, 42],
[42, 42, 42]], [[ 7, 8, 9],
[10, 11, 12]]]) In [117]: arr3d[0]=old_values In [118]: arr3d
Out[118]:
array([[[ 1, 2, 3],
[ 4, 5, 6]], [[ 7, 8, 9],
[10, 11, 12]]])
以此类推,arr3d[1,0]可以访问索引以(1,0)开头的那些值:
In [119]: arr3d[1,0]
Out[119]: array([7, 8, 9])
注意:上面所有这些选取数组子集的例子中,返回的数组都是视图。
切片索引
ndarry的切片语法跟python列表这样的一维对象差不多:
In [120]: arr[1:6]
Out[120]: array([ 1, 2, 3, 4, 64])
高维度对象的花样更多,你可以子啊一个或多个轴上进行切片,也可以跟整数索引混合使用。
In [122]: arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]]) In [123]: arr2d
Out[123]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]]) In [124]: arr2d[:2]
Out[124]:
array([[1, 2, 3],
[4, 5, 6]])
可以看出,它是沿着第0轴切片的。也就是说切片是沿着一个轴向选取元素的。你可以一次传入多个切片,就像传入多个索引那样:
In [125]: arr2d[:2,1:]
Out[125]:
array([[2, 3],
[5, 6]])
像这样进行切片时,只能得到相同维度的数组视图。通过将整数索引和切片混合,可以得到低维度的切片:
In [127]: arr2d[1,:2]
Out[127]: array([4, 5]) In [128]: arr2d[2,:1]
Out[128]: array([7])
注意:只有冒号表示选取整个轴:、
In [129]: arr2d[:,:1]
Out[129]:
array([[1],
[4],
[7]])
自然,对切片表达式的赋值操作也会被扩散到整个选区:
In [130]: arr2d[:2,1:]
Out[130]:
array([[2, 3],
[5, 6]]) In [131]: arr2d[:2,1:]=0 In [132]: arr2d
Out[132]:
array([[1, 0, 0],
[4, 0, 0],
[7, 8, 9]])
布尔型索引
假设我们有一个用于存储数据的数组以及一个存储姓名的数组(含有重复项)。在这里,我们将使用numpy.random中的randn函数生成一些正态分布的随机数据:
In [133]: names=np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe']) In [134]: data=randn(7,4) In [135]: names
Out[135]: array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'], dtype='<U4') In [136]: data
Out[136]:
array([[ 1.49700553, -0.81010655, 1.38541267, 0.77762598],
[-1.04760513, -0.25802261, -0.07125992, -0.03431114],
[-0.49107174, -1.33574227, 0.10408644, -0.46662551],
[ 0.71487411, 1.18651842, -0.34714216, 0.46087672],
[ 0.2254356 , 0.76541494, 0.12525111, -0.92919057],
[-1.20091987, 0.37064336, -0.77465353, 0.43543748],
[ 2.63967324, -0.7687978 , 0.78363981, 0.02063025]])
假设每个名字对应data数组的一行,而我们想选粗话对应与名字'Bob'的所有行。跟算术运算一样,数组的比较运算(如==)也是矢量化的。因此,对names和字符串‘Bob’的比较运算将会产生一个布尔型数组:
n [137]: names=='Bob'
Out[137]: array([ True, False, False, True, False, False, False])
这个布尔型数组可用于数组索引:
In [139]: data[names=='Bob']
Out[139]:
array([[ 1.49700553, -0.81010655, 1.38541267, 0.77762598],
[ 0.71487411, 1.18651842, -0.34714216, 0.46087672]])
布尔型数组的长度必须跟被索引的轴长度一样。因此,还可以将布尔型数组跟切片丶整数混合使用:
In [140]: data[names=='Bob',2:]
Out[140]:
array([[ 1.38541267, 0.77762598],
[-0.34714216, 0.46087672]]) In [141]: data[names=='Bob',3]
Out[141]: array([0.77762598, 0.46087672])
要选择除"Bob"以外的其他值,既可以使用不等于符号(!=),也可以通过符号(-)对条件进行否定:
In [141]: data[names=='Bob',3]
Out[141]: array([0.77762598, 0.46087672]) In [151]: data[~(names == 'Bob')]
Out[151]:
array([[-1.04760513, -0.25802261, -0.07125992, -0.03431114],
[-0.49107174, -1.33574227, 0.10408644, -0.46662551],
[ 0.2254356 , 0.76541494, 0.12525111, -0.92919057],
[-1.20091987, 0.37064336, -0.77465353, 0.43543748],
[ 2.63967324, -0.7687978 , 0.78363981, 0.02063025]])
这里试了下使用符号(-)会报错TypeError: The numpy boolean negative, the `-` operator, is not supported, use the `~` operator or the logical_not function instead.提示,需要使用~符号表示取反
选取这3个名字中的2个需要组合应用多个布尔条件,使用&(和)丶|(或)之类的布尔算术运算符即可:
In [152]: mask=(names=='Bob') |(names=='Will') In [153]: mask
Out[153]: array([ True, False, True, True, True, False, False]) In [154]: data[mask]
Out[154]:
array([[ 1.49700553, -0.81010655, 1.38541267, 0.77762598],
[-0.49107174, -1.33574227, 0.10408644, -0.46662551],
[ 0.71487411, 1.18651842, -0.34714216, 0.46087672],
[ 0.2254356 , 0.76541494, 0.12525111, -0.92919057]])
通过布尔型索引选取数组中的数据,将总是创建数据的副本,即使返回一模一样的数组,也是如此。
通过布尔型数组设置值是一种经常使用的手段。为了将data中所有的负值设置为0:
In [155]: data[data<0]=0 In [156]: data
Out[156]:
array([[1.49700553, 0. , 1.38541267, 0.77762598],
[0. , 0. , 0. , 0. ],
[0. , 0. , 0.10408644, 0. ],
[0.71487411, 1.18651842, 0. , 0.46087672],
[0.2254356 , 0.76541494, 0.12525111, 0. ],
[0. , 0.37064336, 0. , 0.43543748],
[2.63967324, 0. , 0.78363981, 0.02063025]])
通过一维布尔数组设置整行或列的值也很简单:
In [157]: data[names!='Joe']=7 In [158]: data
Out[158]:
array([[7. , 7. , 7. , 7. ],
[0. , 0. , 0. , 0. ],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[7. , 7. , 7. , 7. ],
[0. , 0.37064336, 0. , 0.43543748],
[2.63967324, 0. , 0.78363981, 0.02063025]])
花式索引
花式索引是一个Numpy术语,它指的的是利用整数数组进行索引。假设我们有个8*4的数组:
In [162]: arr=np.empty((8,4)) In [163]: for i in range(8):
...: arr[i]=i
...: In [164]: arr
Out[164]:
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.]])
为了以特定顺序选取子集,只需传入一个用于指定顺序的整数列表或ndarry即可:
In [165]: arr[[4,3,0,6]]
Out[165]:
array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
这段代码确实达到了我们的要求!使用负数索引将会从末尾开始选取行:
In [167]: arr[[-3,-5,-7]]
Out[167]:
array([[5., 5., 5., 5.],
[3., 3., 3., 3.],
[1., 1., 1., 1.]])
一次传入多个索引数组会有一点特别。它返回的是一个一维数组,其中的元素对应哥哥索引元组:
In [169]: arr=np.arange(32).reshape((8,4)) In [170]: arr
Out[170]:
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, 30, 31]]) In [171]: arr[[1,5,7,2],[0,3,1,2]]
Out[171]: array([ 4, 23, 29, 10])
代码中最终选取的䛾(1,0),(5,3),(7,1)和(2,2)。这些花式索引的行为可能跟某些用户的预期不一样,选取矩阵的行列子集应该是矩形区域的形式才对,于是:
In [173]: arr[[1,5,7,2]][:,[0,3,1,2]]
Out[173]:
array([[ 4, 7, 5, 6],
[20, 23, 21, 22],
[28, 31, 29, 30],
[ 8, 11, 9, 10]])
花式索引跟切片不一样,它总是将数据复制到新数组中。
数组转置和轴对换
转置是重塑的一种特殊方式,它返回的是源数据的视图(不会进行任何复制操作)。数组不仅有transpose方法还有一个特殊的T属性:
In [174]: arr=np.arange(15).reshape(3,5) In [175]: arr
Out[175]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]]) In [176]: arr.T
Out[176]:
array([[ 0, 5, 10],
[ 1, 6, 11],
[ 2, 7, 12],
[ 3, 8, 13],
[ 4, 9, 14]])
在进行矩阵计算时,经常需要用到该操作,比如利用np.dot计算矩阵的内积:
In [178]: arr=np.random.randn(6,3) In [179]: np.dot(arr.T,arr)
Out[179]:
array([[ 4.10149347, 0.88541771, -0.47377443],
[ 0.88541771, 5.33214026, -1.6787001 ],
[-0.47377443, -1.6787001 , 6.31781659]])
对于高维度数组,transpose需要得到一个由编号组成的元组才能对这些轴进行转置:
In [180]: arr=np.arange(16).reshape((2,2,4)) In [181]: arr
Out[181]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]], [[ 8, 9, 10, 11],
[12, 13, 14, 15]]]) In [182]: arr.transpose((1,0,2))
Out[182]:
array([[[ 0, 1, 2, 3],
[ 8, 9, 10, 11]], [[ 4, 5, 6, 7],
[12, 13, 14, 15]]])
简单的转置可以使用.T,它其实就是进行轴对换而已。ndarry还有一个swapaxes方法,它需要接受一对轴编号:
In [183]: arr
Out[183]:
array([[[ 0, 1, 2, 3],
[ 4, 5, 6, 7]], [[ 8, 9, 10, 11],
[12, 13, 14, 15]]]) In [184]: arr.swapaxes(1,2)
Out[184]:
array([[[ 0, 4],
[ 1, 5],
[ 2, 6],
[ 3, 7]], [[ 8, 12],
[ 9, 13],
[10, 14],
[11, 15]]])
swapaxes也是返回源数据的视图(不会进行任何复制操作)。
Numpy的ndarry的更多相关文章
- Numpy的ndarry:一种多维数组对象
Numpy的ndarry:一种多维数组对象 Numpy最重要的一个特点就是其N维数组对象(即ndarry),该对象是一个快速而灵活的大数据集容器.你可以利用这种数组对整块数据执行一些数学运算,其语法跟 ...
- numpy基础知识
官网简介: http://www.numpy.org/ ndarry基本属性 ndarry是Numpy中的N维数组对象(N dimentional arrya,ndarray) ndarry中所有的元 ...
- Python numpy的基本操作你一般人都不会
前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. PS:如有需要最新Python学习资料的小伙伴可以加点击下方链接自行获取 ...
- python numpy的基本操作
站长资讯平台:文章目录0.NumPy 与 ndarry1.数组属性查看:类型.尺寸.形状.维度2.numpy元素中数据存储方式,数据类型,类型转换2.1 查看元素数据存储类型2.2 元素数据存储类型转 ...
- Python 学习之 NumPy
NumPy(Numerical Python的简称) 是高性能科学计算和数据分析的基础包,提供了矩阵运算的功能,其一般与Scipy.matplotlib一起使用.其实,list已经提供了类似于矩阵的表 ...
- python numpy 模块简单介绍
用python自带的list去处理数组效率很低, numpy就诞生了, 它提供了ndarry对象,N-dimensional object, 是存储单一数据类型的多维数组,即所有的元素都是同一种类型. ...
- Numpy库(个人学习笔记)
一样,咱的计算机还是得先拥有Python,并且安装了Numpy库.有疑问的话可以看这里呦~~~~ 下面开讲: NumPy的主要对象是齐次多维数组.它是一个元素表(通常是数字),并且都是相同类型,由正整 ...
- 利用Python进行数据分析——Numpy基础:数组和矢量计算
利用Python进行数据分析--Numpy基础:数组和矢量计算 ndarry,一个具有矢量运算和复杂广播能力快速节省空间的多维数组 对整组数据进行快速运算的标准数学函数,无需for-loop 用于读写 ...
- python之科学函数课——Numpy
一般来讲,数据都是由行列表示的,也就是矩阵,类似于Excel表格一样的东西. 首先我们学习一下Numpy,装好anaconda之后默认是装好的,下面是numpy的一些函数库:Numpy是科学计算库,是 ...
随机推荐
- xcode6 添加.pch文件
1, 新建文件 (command+N)ios-选择other组,再次选择PCH File,输入文件名保存. eg: 创建的工程为Demo; 创建文件名为DemoPrefixHeader.pch 2,到 ...
- c语言输出4*5的数列?
1 2 3 4 5 2 4 6 8 10 3 6 9 12 15 4 8 12 16 20 输出上面的数列,用c实现的代码:<pre lang="c" line=&quo ...
- HDU - 5876 :Sparse Graph (完全图的补图的最短路 -BFS&set)
In graph theory, the complement of a graph G is a graph H on the same vertices such that two distinc ...
- ZOJ3640Help Me Escape(师傅逃亡系列•一)(数学期望||概率DP)
Background If thou doest well, shalt thou not be accepted? and if thou doest not well, sin lieth at ...
- Codeforces 620E New Year Tree【线段树傻逼题】
LINK 题目大意 给你一棵树 让你支持子树染色,子树查询颜色个数,颜色数<=60, 节点数<=4e5 思路 因为颜色数很少,考虑状态压缩变成二进制 然后直接在dfs序上用线段树维护就可以 ...
- Win32 程序在启动时激活前一个启动程序的窗口
UWP 程序天生单实例.当然,新 API (10.0.17134)开始也提供了多实例功能.不过,传统 Win32 程序可就要自己来控制单实例了. 本文介绍简单的几个 Win32 方法调用,使 Win3 ...
- 【BZOJ4025】二分图 LCT
[BZOJ4025]二分图 Description 神犇有一个n个节点的图.因为神犇是神犇,所以在T时间内一些边会出现后消失.神犇要求出每一时间段内这个图是否是二分图.这么简单的问题神犇当然会做了,于 ...
- docker swarm mode routing mesh 使用
Docker Engine swarm mode makes it easy to publish ports for services to make them available to resou ...
- 一个简单的selenium实例(一)
1.selenium RC+Eclipse下载安装 java环境 官网下载地址http://www.oracle.com/technetwork/java/javase/downloads/index ...
- bzoj 1001 [BeiJing2006]狼抓兔子——最小割转最短路
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1001 #include<cstdio> #include<cstring& ...