python科学计算(利用numpy创建并访问数组)

利用numpy创建并访问数组

引入numpy包:

import numpy as np

创建np数组

a = np.array([1,2,3,4])
#b = np.array([1,2,3,4],[5,6,7,8]) #报错
c = np.array([[1,2,3,4],[4,5,6,7],[7,8,9,10]])
c1 = np.array(([1,2,3,4],[4,5,6,7],[7,8,9,10]))
# c2 = np.array({[1,2,3,4],[4,5,6,7],[7,8,9,10]})  #报错

# print(a)
# print(c)
# print(c1)
# print(c.dtype)
 '''
# 输出:
# [1 2 3 4]
# [[ 1  2  3  4]
#  [ 4  5  6  7]
#  [ 7  8  9 10]]
# [[ 1  2  3  4]
#  [ 4  5  6  7]
#  [ 7  8  9 10]]
# int32
 '''

获取数组大小

 print(a.shape)
 print(c.shape)
# '''
# 输出:
# (4,)
# (3, 4)
# '''

通过修改数组的shape属性,在保持数组元素个数不变的情况下,改变数组每个轴的长度

c1.shape = 4,3
print(c1)
# '''
# 输出:
# [[ 1  2  3]
#  [ 4  4  5]
#  [ 6  7  7]
#  [ 8  9 10]]
# '''

当某个轴的元素为-1时,将根据数组元素的个数自动计算此轴的长度

 c1.shape = 2 , -1
print(c1)
# '''
# output:
# [[ 1  2  3  4  4  5]
#  [ 6  7  7  8  9 10]]
# '''

使用数组的reshape方法,可以创建一个改变了尺寸的新数组,原数组的shape保持不变

d = a.reshape((2,2))
print(d)
print(a)
# '''
# output
# [[1 2]
#  [3 4]]
# [1 2 3 4]
# '''

注意: 数组a和d其实共享数据存储内存区域,因此修改其中任意一个数组的元素都会同时修改另外一个数组的内容

a[1] = 100
print(a)
print(d)
# '''
# output:
# [  1 100   3   4]
# [[  1 100]
#  [  3   4]]
# '''

dtype可以获得数组的元素类型,也可以通过dtype参数在创建时指定元素类型

b = np.array([[1, 2, 3, 4],[4, 5, 6, 7], [7, 8, 9, 10]], dtype=np.float)
print(b.dtype)
'''
output:
float64
'''

直接用numpy中的函数创建数组
arange函数类似于python的range函数,通过指定开始值、终值和步长来创建一维数组,注意数组不包括终值:

ar = np.arange(0,1,0.1)
print(ar)
'''
output:
[ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9]
'''

linspace函数通过指定开始值、终值和元素个数来创建一维数组,可以通过endpoint关键字指定是否包括终值,缺省设置是包括终值

li = np.linspace(0, 1, 12)
 print(li)
li1 = np.linspace(0, 1, 12,endpoint=0)
print(li1)
'''
output:
[ 0.          0.09090909  0.18181818  0.27272727  0.36363636  0.45454545
  0.54545455  0.63636364  0.72727273  0.81818182  0.90909091  1.        ]
[ 0.          0.08333333  0.16666667  0.25        0.33333333  0.41666667
  0.5         0.58333333  0.66666667  0.75        0.83333333  0.91666667]
'''

logspace函数和linspace类似,不过它创建等比数列,下面的例子

# 产生1(10^0)到100(10^2)、有20个元素的等比数列:
lo = np.logspace(0, 2, 20)
print(lo)
'''
output:
[   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等函数可以从字节序列创建数组

s = "abcdefgh"
fs8 = np.fromstring(s, dtype=np.int8)
fs16 = np.fromstring(s, dtype=np.int16)

print(fs8)
print(fs16)
'''
output:
[ 97  98  99 100 101 102 103 104]
[25185 25699 26213 26727]
'''

注释: Python的字符串实际上是字节序列,每个字符占一个字节,因此如果从字符串s创建一个8bit的整数数组的话,所得到的数组正好就是字符串中每个字符的ASCII编码:
如果从字符串s创建16bit的整数数组,那么两个相邻的字节就表示一个整数,把字节98和字节97当作一个16位的整数,它的值就是98*256+97 = 25185。可以看出内存中是以little endian(低位字节在
前)方式保存数据的

延伸: 利用fromstring读取二进制文件?
如果我们用C语言的二进制方式写了一组double类型的数值到某个文件中,那们可以从此文件读取相应的数据,并通过fromstring函数将其转换为float64类型的数组。

fromfunction函数 的第一个参数为计算每个数组元素的函数,第二个参数为数组的大小(shape),因为它支持多维数组,所以第二个参数必须是一个序列
如:将数组下标转换为数组中对应的值,然后使用此函数创建数组

def func(i):
    return i % 4 + 1    #下标取余后加一

fu1 = np.fromfunction(func, (10,))
print(fu1)
'''
output:[ 1.  2.  3.  4.  1.  2.  3.  4.  1.  2.]
'''
#创建99乘法表
def func2(i, j):
    return (i+1) * (j+1)

fu2 = np.fromfunction(func2, (9,9))
print(fu2)
'''
output:
[[  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 = np.arange(10)
print(a[5])    # 用整数作为下标可以获取数组中的某个元素
print(a[3:5])  # 用范围作为下标获取数组的一个切片,包括a[3]不包括a[5]
print(a[:5])   # 省略开始下标,表示从a[0]开始
print(a[:-1])  # 下标可以使用负数,表示从数组后往前数
a[2:4] = 100,101  # 下标还可以用来修改元素的值
print(a)
print(a[1:-1:2])  # 范围中的第三个参数表示步长,2表示隔一个元素取一个元素
print(a[::-1])    # 省略范围的开始下标和结束下标,步长为-1,整个数组头尾颠倒
print(a[5:1:-2])  # 步长为负数时,开始下标必须大于结束下标

注意: 和Python的列表序列不同,通过下标范围获取的新的数组是原始数组的一个视图。它与原始数组共享同一块数据空间

a = np.arange(10)
b = a[3:7] # 通过下标范围产生一个新的数组b,b和a共享同一块数据空间
print(b)   #output:[3 4 5 6]
b[2] = 100
print(a,b)
'''
a、b都变了
output:
[  0   1   2   3   4 100   6   7   8   9] 
[  3   4 100   6]
'''

如何不共享数据空间?
1、使用整数序列,整数序列可以是列表或者数组。

x = np.arange(10,1,-1)
x2 = x[[3, 3, 1, 8]]
x1 = x[np.array([3,3,-3,8])]    #下标可以为负
x1[2] = 100
x2[2] = 100
print(x1)    #output:[  7   7 100   2]
print(x2)    #output:[  7   7 100   2]
print(x)     #output:[10  9  8  7  6  5  4  3  2]
x[[3,5,1]] = -1, -2, -3  # 整数序列下标也可以用来修改元素的值
print(x)    #output:[10 -3  8 -1  6 -2  4  3  2]

2、使用布尔数组

x = np.arange(5,0,-1)    #[5, 4, 3, 2, 1]
x1 =  x[np.array([True, False, True, False, False])]
# 布尔数组中下标为0,2的元素为True,因此获取x中下标为0,2的元素
print(x1)   #[5, 3]
x2 =  x[[True, False, True, False, False]]
# 如果是布尔列表,则把True当作1, False当作0,按照整数序列方式获取x中的元素
print(x2)    #[4, 5, 4, 5, 5]
x3 = x[np.array([True, False, True, True])]
# 布尔数组的长度不够时,不够的部分都当作False
print(x3)    #[5, 3, 2]
x[np.array([True, False, True, True])] = -1, -2, -3
# 布尔数组下标也可以用来修改元素
print(x)    #[-1, 4, -2, -3, 1]

产生 一个长度为10,元素值为0-1的随机数的数组

x = np.random.rand(10) 
print(x)
'''
[ 0.72223939, 0.921226 , 0.7770805 , 0.2055047 , 0.17567449,
0.95799412, 0.12015178, 0.7627083 , 0.43260184, 0.91379859]
'''

利用布尔数组提取满足条件的数组中的元素

p = x > 0.5    # 数组x中的每个元素和0.5进行大小比较,得到一个布尔数组,True表示x中对应的值大于0.5
print(p)       #[ True  True  True False False False False False  True False]
print(x[p])    #[ 0.5764845   0.84377671  0.91877546  0.54866511]

猜你喜欢

转载自blog.csdn.net/weixin_42216171/article/details/86154297