python科学计算——numpy(1)

时间:2022-11-15 21:28:14
导入numpy:
from numpy import *


创建array:
c = array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]], dtype=np.float)
其中dtype指明数据类型


通过c.shape可以获得数组的大小
c的第0轴的长度为3,第1轴的长度为4


在保持数组元素个数不变的情况下,改变数组每个轴的长度:
c.shape = 4,3
当某个轴的元素为-1时,将根据数组元素的个数自动计算此轴的长度,因此下面的程序将数组c的shape改为了(2,6):
>>> c.shape = 2,-1
>>> c
array([[ 1,  2,  3,  4,  4,  5],
       [ 6,  7,  7,  8,  9, 10]])


使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape保持不变:
d = a.reshape((2,2))
数组a和d其实共享数据存储内存区域,因此修改其中任意一个数组的元素都会同时修改另外一个数组的内容


arange函数:
arange函数类似于python的range函数,通过指定开始值、终值和步长来创建一维数组
如:
arange(0,1,0.1)
array([ 0. ,  0.1,  0.2,  0.3,  0.4,  0.5,  0.6,  0.7,  0.8,  0.9])
创建了一个一位数组,从0开始,到1(不包括1)结束,步长为0.1


linspace函数:
通过指定开始值、终值和元素个数来创建一维数组,可以通过endpoint关键字指定是否包括终值,缺省设置是包括终值
>>> linspace(0,1,9,0)  #不包括终值1,步长为1/9
array([ 0.        ,  0.11111111,  0.22222222,  0.33333333,  0.44444444,
        0.55555556,  0.66666667,  0.77777778,  0.88888889])
>>> linspace(0,1,9,1)  #包括终值1,步长为1/(9-1)
array([ 0.   ,  0.125,  0.25 ,  0.375,  0.5  ,  0.625,  0.75 ,  0.875,  1.   ])


logspace函数:
logspace(起始值(10的多少次方), 终止值(10的多少次方), 20(元素个数))
logspace函数和linspace类似,不过它创建等比数列,下面的例子产生1(10^0)到100(10^2)、有20个元素的等比数列:
如:
>>>logspace(0, 2, 20)
array([   1.        ,    1.27427499,    1.62377674,    2.06913808,
          2.6366509 ,    3.35981829,    4.2813324 ,    5.45559478,
          6.95192796,    8.8586679 ,   11.28837892,   14.38449888,
         18.32980711,   23.35721469,   29.76351442,   37.92690191,
         48.32930239,   61.58482111,   78.47599704,  100.        ])


frombuffer, fromstring, fromfile等函数可以从字节序列创建数组,下面以fromstring为例:
>>> from numpy import *
>>> s="abcdefg"
>>> fromstring(s,dtype=int8)
array([ 97,  98,  99, 100, 101, 102, 103], dtype=int8)
Python的字符串实际上是字节序列,每个字符占一个字节,因此如果从字符串s创建一个8bit的整数数组的话,所得到的数组正好就是字符串中每个字符的ASCII编码
如果从字符串s创建16bit的整数数组,那么两个相邻的字节就表示一个整数,把字节98和字节97当作一个16位的整数,它的值就是98*256+97 = 25185。可以看出内存中是以little endian(低位字节在前)方式保存数据的。
即为低位放在低地址处




fromfunction函数:
fromfunction函数的第一个参数为计算每个数组元素的函数,第二个参数为数组的大小(shape),因为它支持多维数组,所以第二个参数必须是一个序列
下面的例子创建一个二维数组表示九九乘法表,输出的数组a中的每个元素a[i, j]都等于func2(i, j):


>>> def func2(i, j):
...     return (i+1) * (j+1)
...
>>> a = fromfunction(func2, (9,9))
>>> a
array([[  1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.],
       [  2.,   4.,   6.,   8.,  10.,  12.,  14.,  16.,  18.],
       [  3.,   6.,   9.,  12.,  15.,  18.,  21.,  24.,  27.],
       [  4.,   8.,  12.,  16.,  20.,  24.,  28.,  32.,  36.],
       [  5.,  10.,  15.,  20.,  25.,  30.,  35.,  40.,  45.],
       [  6.,  12.,  18.,  24.,  30.,  36.,  42.,  48.,  54.],
       [  7.,  14.,  21.,  28.,  35.,  42.,  49.,  56.,  63.],
       [  8.,  16.,  24.,  32.,  40.,  48.,  56.,  64.,  72.],
       [  9.,  18.,  27.,  36.,  45.,  54.,  63.,  72.,  81.]])


元素的读取:
>>> a = arange(10)
>>> a[5]    # 用整数作为下标可以获取数组中的某个元素
5
>>> a[3:5]  # 用范围作为下标获取数组的一个切片,包括a[3]不包括a[5]
array([3, 4])
>>> a[:5]   # 省略开始下标,表示从a[0]开始
array([0, 1, 2, 3, 4])
>>> a[:-1]  # 下标可以使用负数,表示从数组后往前数
array([0, 1, 2, 3, 4, 5, 6, 7, 8])
>>> a[2:4] = 100,101    # 下标还可以用来修改元素的值
>>> a
array([  0,   1, 100, 101,   4,   5,   6,   7,   8,   9])
>>> a[1:-1:2]   # 范围中的第三个参数表示步长,2表示隔一个元素取一个元素
array([  1, 101,   5,   7])
>>> a[::-1] # 省略范围的开始下标和结束下标,步长为-1,整个数组头尾颠倒
array([  9,   8,   7,   6,   5,   4, 101, 100,   1,   0])
>>> a[5:1:-2] # 步长为负数时,开始下标必须大于结束下标
array([  5, 101])
注意:和Python的列表序列不同,通过下标范围获取的新的数组是原始数组的一个视图。它与原始数组共享同一块数据空间


使用整数序列
当使用整数序列对数组元素进行存取时,将使用整数序列中的每个元素作为下标,整数序列可以是列表或者数组。使用整数序列作为下标获得的数组不和原始数组共享数据空间。
>>> x = np.arange(10,1,-1)
>>> x
array([10,  9,  8,  7,  6,  5,  4,  3,  2])
>>> x[[3, 3, 1, 8]] # 获取x中的下标为3, 3, 1, 8的4个元素,组成一个新的数组
array([7, 7, 9, 2])
>>> b = x[np.array([3,3,-3,8])]  #下标可以是负数
>>> b[2] = 100
>>> b
array([7, 7, 100, 2])
>>> x   # 由于b和x不共享数据空间,因此x中的值并没有改变
array([10,  9,  8,  7,  6,  5,  4,  3,  2])
>>> x[[3,5,1]] = -1, -2, -3 # 整数序列下标也可以用来修改元素的值
>>> x
array([10, -3,  8, -1,  6, -2,  4,  3,  2])


布尔数组的应用:
布尔数组只能用列表,实质就是返回对应下标值为True的元素
>>> x = random.rand(10) # 产生一个长度为10,元素值为0-1的随机数的数组
>>> x
array([ 0.72223939,  0.921226  ,  0.7770805 ,  0.2055047 ,  0.17567449,
        0.95799412,  0.12015178,  0.7627083 ,  0.43260184,  0.91379859])
>>> x>0.5
>>> # 数组x中的每个元素和0.5进行大小比较,得到一个布尔数组,True表示x中对应的值大于0.5
array([ True,  True,  True, False, False,  True, False,  True, False,  True], dtype=bool)
>>> x[x>0.5]
>>> # 使用x>0.5返回的布尔数组收集x中的元素,因此得到的结果是x中所有大于0.5的元素的数组
array([ 0.72223939,  0.921226  ,  0.7770805 ,  0.95799412,  0.7627083 ,
        0.91379859])




结构数组:
假设我们需要定义一个结构数组,它的每个元素都有name, age和weight字段。在NumPy中可以如下定义:
persontype = np.dtype({
    'names':['name', 'age', 'weight'],
    'formats':['S32','i', 'f']})  #创建persontype结构,用字典指定names和formats参数,字段名和字段类型都用用list表示
a = np.array([("Zhang",32,75.5),("Wang",24,65.2)],
    dtype=persontype)


结构像字典一样可以通过字符串下标获取其对应的字段值:


>>> a[0]["name"]
'Zhang'
我们不但可以获得结构元素的某个字段,还可以直接获得结构数组的字段,它返回的是原始数组的视图,因此可以通过修改b[0]改变a[0]["age"]:


>>> b=a[:]["age"] # 或者a["age"]
>>> b
array([32, 24])
>>> b[0] = 40
>>> a[0]["age"]
40