Numpy笔记(NumPy ndarray)
本篇笔记是根据学习《Python for data analysis》这本英文教程里的Numpy这一部分来记录的。这本书在网上的评价还是很高的,里面讲的东西也比较细,鉴于是英文的,所以我就打算只挑部分来看,时间充裕的同学可以从头到尾的细看一遍。
Numpy,是Numerical Python的简写,它是Python里数字计算的最重要的一个基础包。
The NumPy ndarray: A Multidimensional Array Object
Numpy ndarray:一个多维数组对象
Numpy 的一个关键的特点是其N-维数组对象,或者叫做ndarray,它是一个快速的,灵活的大数据python“容器”。Arrays使得你可以对整个block使用简单的语法来进行数学计算。举个例子,导入Numpy并且生成一个小的随机数组:
#首先进入ipython,具体方法请见我前一篇文章
#这里你可以使用shell,或者web界面,根据你喜好来
$ ipython
Python 3.7.6 (default, Jan 8 2020, 19:59:22)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.12.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: import numpy as np #导入Numpy
In [2]: data = np.random.randn(2,3) #生成随机数组,2个数组,每个里面3个元素
In [3]: data
Out[3]:
array([[ 0.01738749, -0.05367916, 0.72654692],
[ 1.45506185, -0.71293169, 1.35346708]])
对数组进行数学运算:
In [4]: data*10
Out[4]:
array([[ 0.17387488, -0.53679156, 7.26546924],
[14.55061854, -7.12931685, 13.53467077]])
In [5]: data+data
Out[5]:
array([[ 0.03477498, -0.10735831, 1.45309385],
[ 2.91012371, -1.42586337, 2.70693415]])
ndarray是用于存放同种数据的多维“容器”,也就是说,所有的元素必须是同样的类型。每一个数组都有自己的shape,用shape
可以查看每一个维度的大小;使用dtype
可以查看数组内的数据类型:
In [6]: data.shape
Out[6]: (2, 3)
In [7]: data.dtype
Out[7]: dtype('float64')
NOTE: Whenever you see “array,” “NumPy array,” or “ndarray” in the text,
with few exceptions they all refer to the same thing: the ndarray object.
Creating ndarrays
创建一个ndarray的最简单的方法就是使用array
功能。比如说:
In [8]: data1 = [6, 7.5, 8, 0, 1]
In [9]: arr1 = np.array(data1)
In [10]: arr1
Out[10]: array([6. , 7.5, 8. , 0. , 1. ])
或者你想创建嵌套序列,比如等长列表,将会被转换为多维数组:
In [11]: data2 = [[1, 2, 3, 4], [5, 6, 7, 8]]
In [12]: arr2 = np.array(data2)
In [13]: arr2
Out[13]:
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
因为data2是一个由list组成的list,所以arr2的shape是一个二维的数组。你可以用ndim
和shape
来检查:
In [14]: arr2.ndim #看维度
Out[14]: 2
In [15]: arr2.shape
Out[15]: (2, 4)
In [16]: arr2.dtype
Out[16]: dtype('int64') #数组内数据类型是int整数
另外,np.array
还有很多其他的功能来创建新的arrays。比如说,它可以创建全是1或者全是0的array。还可以创建一个空的array,即没有确定值:
In [17]: np.zeros(10) #创建全是0的一维数组
Out[17]: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
In [18]: np.zeros((3,6)) #创建全是0的二维数组
Out[18]:
array([[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.]])
In [19]: np.empty((2,3,2)) #创建空数组
Out[19]:
array([[[6.95334423e-310, 0.00000000e+000],
[0.00000000e+000, 0.00000000e+000],
[0.00000000e+000, 0.00000000e+000]],
[[0.00000000e+000, 0.00000000e+000],
[0.00000000e+000, 0.00000000e+000],
[0.00000000e+000, 0.00000000e+000]]])
有的时候,
np.empty
创建的空数组,返回值不是0,而是一堆乱七八糟的值,也就是“garbage” values。
Data Types for ndarrays
在你创建一个ndarray的时候,你可以指定这个ndarray里的数据类型是什么,比如说:
In [20]: arr1 = np.array([1, 2, 3], dtype=np.float64)
In [21]: arr1
Out[21]: array([1., 2., 3.])
In [22]: arr2 = np.array([1, 2, 3], dtype=np.int32)
In [23]: arr2
Out[23]: array([1, 2, 3], dtype=int32)
In [24]: arr1.dtype
Out[24]: dtype('float64')
In [25]: arr2.dtype
Out[25]: dtype('int32')
此外,你也可以更改一个数组的数据类型:
In [26]: arr = np.array([1, 2, 3, 4, 5])
In [27]: arr.dtype
Out[27]: dtype('int64')
In [28]: float_arr = arr.astype(np.float64) #把整数类型改成浮点类型
In [29]: float_arr.dtype
Out[29]: dtype('float64')
相反,你也可以把浮点类型改成整数,但是小数部分就会被截掉:
In [30]: arr = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
In [31]: arr
Out[31]: array([ 3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
In [32]: arr.astype(np.int32)
Out[32]: array([ 3, -1, -2, 0, 12, 10], dtype=int32)
如果你的数组内是字符串类型,也可以使用这种方法进行转换:
In [33]: numeric_strings = np.array(['1.25', '-9.6', '42'], dtype=np.string_)
In [34]: numeric_strings.astype(float)
Out[34]: array([ 1.25, -9.6 , 42. ])
在使用
numpy.string_
进行数据类型转换的时候需要注意,有的时候会在没有任何提示下截断你的数据。
Arithmetic(运算) with NumPy Arrays
array很重要,因为它们使你能够对数据批量处理操作,而不需要编写任何for循环。NumPy用户称之为向量化。任何算术必须在相同大小数组之间进行操作:
In [35]: arr = np.array([[1., 2., 3.], [4., 5., 6.]])
In [36]: arr
Out[36]:
array([[1., 2., 3.],
[4., 5., 6.]])
In [37]: arr*arr
Out[37]:
array([[ 1., 4., 9.],
[16., 25., 36.]])
In [38]: 1/arr
Out[38]:
array([[1. , 0.5 , 0.33333333],
[0.25 , 0.2 , 0.16666667]])
In [39]: arr**0.5
Out[39]:
array([[1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974]])
你还可以比较两个不同的array的大小,这里比较的时候是数组之间相同位置进行比较:
In [40]: arr2 = np.array([[0., 4., 1.], [7., 2., 12.]])
In [41]: arr2
Out[41]:
array([[ 0., 4., 1.],
[ 7., 2., 12.]])
In [42]: arr2>arr
Out[42]:
array([[False, True, False],
[ True, False, True]])
Basic Indexing(索引) and Slicing(切片)
在Numpy里,你有很多种方法可以在data里选择一个subset,或者选择出某一个元素。对于一维数组来说是非常简单的:
In [43]: arr=np.arange(10)
In [44]: arr
Out[44]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [45]: arr[5]
Out[45]: 5
In [46]: arr[5:8]
Out[46]: array([5, 6, 7])
In [47]: arr[5:8]=12 #从索引的第5位到第7位改成12(这里涉及python的索引规则)
In [48]: arr
Out[48]: array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
对数组进行“切片”:
In [49]: arr_slice=arr[5:8]
In [50]: arr_slice
Out[50]: array([12, 12, 12])
对切出来的“片段”进行修改:
In [51]: arr_slice[1]=12345
In [52]: arr #对切片的修改会影响整个原始数组
Out[52]:
array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8,
9])
对于二维数组来说:
In [53]: arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
In [54]: arr2d[2]
Out[54]: array([7, 8, 9])
In [55]: arr2d[0][2]
Out[55]: 3
In [56]: arr2d[0,2] #这样的表示方法可以参考下面的示意图来进行理解
Out[56]: 3
那如果是多维数组呢?比如现在有一个2 × 2 × 3 array:
In [57]: arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
In [58]: arr3d
Out[58]:
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
In [59]: arr3d[0]
Out[59]:
array([[1, 2, 3],
[4, 5, 6]])
更改多维数组里的数据:
In [60]: old_values=arr3d[0].copy()
In [61]: arr3d[0]=42 #更改其中一个元素,使得这个元素里的所有值都变成42
In [62]: arr3d
Out[62]:
array([[[42, 42, 42],
[42, 42, 42]],
[[ 7, 8, 9],
[10, 11, 12]]])
In [63]: arr3d[0]=old_values #再改回来
In [64]: arr3d
Out[64]:
array([[[ 1, 2, 3],
[ 4, 5, 6]],
[[ 7, 8, 9],
[10, 11, 12]]])
对多维数组切片:
In [65]: arr3d[1,0]
Out[65]: array([7, 8, 9])
In [66]: arr2d
Out[66]:
array([[1, 2, 3],
[4, 5, 6],
[7, 8, 9]])
In [67]: arr2d[:2]
Out[67]:
array([[1, 2, 3],
[4, 5, 6]])
In [68]: arr2d[:2,1:] #在二维数组里取第0和1个索引对应的list,然后在这两个list里取从索引1开始,到最后的元素
Out[68]:
array([[2, 3],
[5, 6]])
In [69]: arr2d[1,:2] #取索引是1的list,然后在这个list里取从开始到索引为2(不包括2)的元素
Out[69]: array([4, 5])
有关二维数组的切片的索引位置,可以参考下图:
将数组里小于0的数都设置为0:
In [70]: data = np.random.randn(7, 4)
In [71]: data
Out[71]:
array([[ 1.07484753, -1.37075898, -1.76641029, 1.39686773],
[ 1.12808743, 0.38325471, 2.26384631, 1.21861537],
[-0.37522887, -1.2066686 , -0.07729884, 1.76493675],
[ 0.51771666, 0.14024697, 0.91802525, 0.88580838],
[-0.17494945, -0.14744639, 0.82242766, -0.060019 ],
[ 1.11820368, -1.18942934, 1.34140358, -0.9074736 ],
[ 0.01312651, -2.17228966, 0.97890648, 1.51395293]])
In [72]: data[data<0]=0
In [73]: data
Out[73]:
array([[1.07484753, 0. , 0. , 1.39686773],
[1.12808743, 0.38325471, 2.26384631, 1.21861537],
[0. , 0. , 0. , 1.76493675],
[0.51771666, 0.14024697, 0.91802525, 0.88580838],
[0. , 0. , 0.82242766, 0. ],
[1.11820368, 0. , 1.34140358, 0. ],
[0.01312651, 0. , 0.97890648, 1.51395293]])
Fancy Indexing
花式索引是NumPy采用的术语,用于描述对整数数组进行索引:
In [74]: arr=np.empty((8,4)) #比如先创建一个8*4的空数组
In [75]: arr #这就是上面说到的,有时候你创建的空数组不是每次都会是0
Out[75]:
array([[ 6.95334381e-310, 0.00000000e+000, 6.93002310e-310,
4.34669976e-118],
[ 6.93002307e-310, 6.93002310e-310, 1.04440620e+181,
6.93002307e-310],
[ 6.93002310e-310, -1.76250980e-304, 6.93002307e-310,
6.93002310e-310],
[ 8.10582968e-283, 6.93002307e-310, 6.93002310e-310,
2.58280046e+280],
[ 6.93002308e-310, 6.93002461e-310, 1.20122413e+036,
6.93002307e-310],
[ 6.93002461e-310, 6.39556658e-245, 6.93002307e-310,
6.93002461e-310],
[ 9.69473502e+012, 6.93002307e-310, 6.93002461e-310,
2.99497312e+029],
[ 6.93002307e-310, 6.93002461e-310, -2.36433447e+212,
6.93002307e-310]])
In [76]: for i in range(8): #给这个空数组赋值
...: arr[i]=i
...:
In [77]: arr
Out[77]:
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.]])
选择你想提取的subset,并按照特定顺序排列:
In [78]: arr[[4,3,0,6]]
Out[78]:
array([[4., 4., 4., 4.],
[3., 3., 3., 3.],
[0., 0., 0., 0.],
[6., 6., 6., 6.]])
In [79]: arr[[-3,-5,-7]] #负数表示从倒数顺序来取subset
Out[79]:
array([[5., 5., 5., 5.],
[3., 3., 3., 3.],
[1., 1., 1., 1.]])
通用函数
In [1]: import numpy as np
In [2]: arr = np.arange(10)
In [3]: arr
Out[3]: array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [4]: np.sqrt(arr) #计算每一个元素的开方
Out[4]:
array([0. , 1. , 1.41421356, 1.73205081, 2. ,
2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ])
In [5]: np.exp(arr) #numpy.exp():返回e的幂次方,e是一个常数为2.71828
Out[5]:
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])
Unique
针对一维数组,这个函数是把数组里“不重复的”元素挑选出来。
In [11]: names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
In [12]: np.unique(names)
Out[12]: array(['Bob', 'Joe', 'Will'], dtype='
版权声明:
作者:zhangchen
链接:https://www.techfm.club/p/17768.html
来源:TechFM
文章版权归作者所有,未经允许请勿转载。
共有 0 条评论