1、背景介绍(introduction)
在数值计算领域,说Numpy是python最重要的包也不为过。在numpy中有下面这些东西: nadarry,一种高效多维数组,提供了基于数组的便捷算术操作及灵活的广播功能。(broadcasting) 便利的数组函数 用于读取/写入(reading/writing)数据到磁盘的便利工具 线性代数,随机生成,傅里叶变换能力 可以用CAPI来写C,C++,或FORTRAN 通过学习理解numpy中数组和数组的导向计算,能帮我们理解pandas之类的工具。
2、方法及数据(methonds and data)
2.1The Numpy ndarray: A Multidimensional Array Object(nadarry:多维数组对象)
N-dimensisonal array object(n维数组对象),or ndarray,这是numpy的关键特征。先来尝试一下,生成一个随机数组:
In [6]:
import numpy as np
In [4]:
# Generate some random data生成随机数组
data = np.random.randn(2,3)
设置种子(随便设置一个有趣的数字),确保每次生成的随机数是一致的。如果不设置那嚒每次随机的数组 不一样
In [5]:
np.random.seed(123)
In [6]:
data
Out[6]:
array([[ 0.46135328, 0.32250428, -0.19077805],
[ 1.06864943, 0.05923916, -0.10650734]])
In [7]:
data.ndim
Out[7]:
2
一个ndarray是一个通用的多维数组的同类数据容器,也就是说它包含的每一个元素均为相同类型。每个数组都有一个shape,来表示维数的大小,而用dtype表示数据的类型
In [8]:
data.shape
Out[8]:
(2, 3)
In [9]:
data.dtype
Out[9]:
dtype('float64')
进行一些数学运算
In [10]:
data*10
Out[10]:
array([[ 4.61353275, 3.22504279, -1.90778049],
[10.6864943 , 0.59239157, -1.06507342]])
In [11]:
data+data
Out[11]:
array([[ 0.92270655, 0.64500856, -0.3815561 ],
[ 2.13729886, 0.11847831, -0.21301468]])
In [12]:
al=np.array([[1,2],[3,4],[5,6]])
al
Out[12]:
array([[1, 2],
[3, 4],
[5, 6]])
In [13]:
al*al
Out[13]:
array([[ 1, 4],
[ 9, 16],
[25, 36]])
实现数组的转置,T
In [14]:
al.T
Out[14]:
array([[1, 3, 5],
[2, 4, 6]])
把一个数组的维数转换成另一个数组,实现重构reshape()
In [22]:
al.reshape(2,3)
Out[22]:
array([[1, 2, 3],
[4, 5, 6]])
实现数组的点乘dot 下面维al数组与其转置数组的乘积,最终为3*3
In [25]:
al.dot(al.T)
Out[25]:
array([[ 5, 11, 17],
[11, 25, 39],
[17, 39, 61]])
2.1.1创建n维数组,生成ndarray
In [13]:
datal=[6,7.5,80,1]
arr1=np.array(datal)
arr1
Out[13]:
array([ 6. , 7.5, 80. , 1. ])
嵌套序列能被转换为多维数组:
In [12]:
data2=[[1,2,3,4],[5,6,7,8]]
arr2=np.array(data2)
arr2
Out[12]:
array([[1, 2, 3, 4],
[5, 6, 7, 8]])
因为data2是一个包含列表的列表(list of lists), 所以arr2维数为2,我们能用ndim和shape属性夹来确认
In [5]:
print(arr2.ndim)
print(arr2.shape)
2
(2, 4)
除非主动声明,否则np.array会自动推断生成的数据类型,并存储在一个特殊的元数据dtype中
In [14]:
arr1.dtype
Out[14]:
dtype('float64')
In [22]:
arr2.dtype
Out[22]:
dtype('int32')
除了np.array,还有一些其他函数能创建数组,比如给定长度及形状后,zeros可以一次性创造全0数组,ones可以一次性创造全1数组。empty可以创建一个没有初始化数值的数组
In [27]:
np.zeros(10) #生成全为0的一维数组,参数为shape
Out[27]:
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
In [36]:
np.zeros((3,6)) #生成全为0的二维数组
Out[36]:
array([[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.],
[0., 0., 0., 0., 0., 0.]])
In [35]:
np.empty((2,3,2)) #empty并不能保证返回的所有是0的数组,某些情况下,会返回为初始化的垃圾数值,比如上面
Out[35]:
array([[[1.19014900e-311, 3.16202013e-322],
[0.00000000e+000, 0.00000000e+000],
[0.00000000e+000, 1.34033316e-075]],
[[2.16612719e+184, 1.79253058e+160],
[7.62780957e+169, 1.09395731e-042],
[1.21544411e-046, 2.46364746e+184]]])
arrange是一个数组版的Python range函数:
In [43]:
np.arange(3,8,2) #括号参数(i,j,k),i为起始值,j为终值,k为步长
Out[43]:
array([3, 5, 7])
In [6]:
np.arange(15).reshape(3,5) #'int' object is not callable
Out[6]:
array([[ 0, 1, 2, 3, 4],
[ 5, 6, 7, 8, 9],
[10, 11, 12, 13, 14]])
2.1.2 Data Types for ndarrays(ndarray的数据类型)
dtype保存数据的类型:
In [30]:
arr3=np.array([1,2,3],dtype=np.float64)
In [31]:
arr3
Out[31]:
array([1., 2., 3.])
In [32]:
arr4=np.array([1,2,3],dtype=np.int32)
In [33]:
arr4.dtype
Out[33]:
dtype('int32')
可以使用astype方法显式地转换数组的数据类型
In [15]:
arr=np.array([1,2,3,4,5])
In [16]:
arr.dtype
Out[16]:
dtype('int32')
In [17]:
float_arr=arr.astype(np.float64)
In [18]:
float_arr.dtype
Out[18]:
dtype('float64')
In [19]:
arr=np.array([3.7,-1.2,-2.6,0.5,12.9,10.1])
In [20]:
arr
Out[20]:
array([ 3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
In [21]:
arr.astype(np.int32)
Out[21]:
array([ 3, -1, -2, 0, 12, 10])
如果你有一个数组,里面的元素都是表达数字含义的字符串,也可以通过astype将字符串转换为数字
In [24]:
numeric_strings=np.array(['1.25','-9.6','42'],dtype=np.string_)
In [25]:
numeric_strings.astype(float)
Out[25]:
array([ 1.25, -9.6 , 42. ])
如果因为某些原因导致转换类型失败(比如字符串无法砖混为float64位时),将会抛出一个valueerror。这里我们可以使用float来代替np.float64,时因为NumPy可以使用相同别名来表征与Python精度相同的Python数据类型
In [26]:
in_array=np.arange(10)
In [27]:
calibers=np.array([.22,.270,.357,.380,.44,.50],dtype=np.float64)
In [28]:
in_array.astype(calibers.dtype)
Out[28]:
array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
也可以用类型代码来传入数据类型
In [29]:
empty_uint32=np.empty(8,dtype='u4')
In [30]:
empty_uint32
Out[30]:
array([0, 0, 0, 0, 0, 0, 0, 0], dtype=uint32)
2.1.3 NumPy数组算数
In [31]:
arr=np.array([[1.,2.,3.],[4.,5.,6.]])
In [32]:
arr
Out[32]:
array([[1., 2., 3.],
[4., 5., 6.]])
In [33]:
arr*arr
Out[33]:
array([[ 1., 4., 9.],
[16., 25., 36.]])
In [34]:
1/arr
Out[34]:
array([[1. , 0.5 , 0.33333333],
[0.25 , 0.2 , 0.16666667]])
In [35]:
arr**0.5
Out[35]:
array([[1. , 1.41421356, 1.73205081],
[2. , 2.23606798, 2.44948974]])
同尺寸数组之间比较,会产生一个布尔值数组
In [36]:
arr2=np.array([[0.,4.,1.],[7.,2.,12.]])
In [37]:
arr2
Out[37]:
array([[ 0., 4., 1.],
[ 7., 2., 12.]])
In [39]:
arr2>arr
Out[39]:
array([[False, True, False],
[ True, False, True]])
2.1.4 Basic Indexing and Slicing(基本的索引和切片)
有多种方式可以让我们选中数据的子集或者某个单个元素
In [7]:
arr=np.arange(10)
In [8]:
arr
Out[8]:
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
In [9]:
arr[5]
Out[9]:
5
In [10]:
arr[5:8]
Out[10]:
array([5, 6, 7])
In [11]:
arr[5:8]=12 #数值被传递给了整个切片
In [12]:
arr
Out[12]:
array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
In [13]:
arr[[2,3,5]] #实现跳着取值
Out[13]:
array([ 2, 3, 12])
数组的切片是原数组的视图,这意味着数组并不是被复制,任何对于数组的修改都会反映到原数组上
In [14]:
arr_slice=arr[5:8]
In [15]:
arr_slice
Out[15]:
array([12, 12, 12])
当改变arr_slice,变化也会体现在原数组上
In [16]:
arr_slice[1]=1234
In [17]:
arr
Out[17]:
array([ 0, 1, 2, 3, 4, 12, 1234, 12, 8, 9])
不写切片值[:]将会引用数组的所有值
In [18]:
arr_slice[:]=64
In [19]:
arr
Out[19]:
array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])
在一个二维数组中,每个索引值对应的元素不再是一个值,而是一个一维数组
In [20]:
arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]])
In [21]:
arr2d[2]
Out[21]:
array([7, 8, 9])
我们可以通过传递索引的都好分隔列表取选择单个元素,下面两种方法都可以取出矩阵中的元素
In