数据分析(1) Numpy数组

  Numpy的数组类被称作ndarray通常被称作数组。

  特点:元素类型相同,数量事先给定。

1 创建方式

  (1)array( ):接收一个普通的Python序列(元组与列表并无区别),并将其转换为ndarray

# 使用列表创建
list1 = [1, 2, 3, 4, 5]
print('使用一维列表创建:\n', np.array(list1))
list2 = [[1, 2, 3], [4, 5, 6]]
print('使用二维列表创建:\n', np.array(list2))
# 使用元组创建
tuple1 = (1, 2, 3, 4, 5)
print('使用一维元组创建:\n', np.array(tuple1))
tuple2 = ((1, 2, 3), (4, 5, 6))
print('使用二维元组创建:\n', np.array(tuple2))

# 使用一维列表创建:
#  [1 2 3 4 5]
# 使用二维列表创建:
#  [[1 2 3]
#  [4 5 6]]
# 使用一维元组创建:
#  [1 2 3 4 5]
# 使用二维元组创建:
#  [[1 2 3]
#  [4 5 6]]

  (2zeros( ):创建指定长度/形状的全0数组

print('一维全0数组:\n', np.zeros(3))
print('二维全0数组:\n', np.zeros((2, 3)))
# 一维全0数组: # [0. 0. 0.] # 二维全0数组: # [[0. 0. 0.] # [0. 0. 0.]]

  (3)ones( ):创建指定长度/形状的全1数组

print('一维全1数组:\n', np.ones(3))
print('二维全1数组:\n', np.ones((2, 3)))
# 一维全1数组: # [1. 1. 1.] # 二维全1数组: # [[1. 1. 1.] # [1. 1. 1.]]

  (4)empty( ):创建一个未初始化的ndarray多维数组,注意empty( )创建的数组中的数值是无意义的。 

print('一维空数组:\n', np.empty(3))
print('二维空数组:\n', np.empty((2, 3)))
# 一维空数组: # [1. 1. 1.] # 二维空数组: # [[1. 1. 1.] # [1. 1. 1.]]

  (5)arange( )类似Pythonrange函数,通过[start, end, step)创建一维数组 

print(np.arange(5))     # [0 1 2 3 4]
print(np.arange(5, 10))     # [5 6 7 8 9]
print(np.arange(10, 20, 2))     # [10 12 14 16 18] 

  (6) linspace( ):通过指定开始值、终值和元素个数来创建一个一维数组,数组的数据元素符合等差数列,可以通过endpoint关键字指定是否包含终值,默认包含终值

print(np.linspace(0, 10, 5))    # [ 0.   2.5  5.   7.5 10. ]
print(np.linspace(0, 10, 5, endpoint=False))    # [0. 2. 4. 6. 8.]

  (7)logspace( ):和linspace函数类似,不过创建的是等比数列数组

print(np.logspace(0, 2, 5))     # [  1.           3.16227766  10.          31.6227766  100.        ]

  (8)随机数:使用随机数填充数组

    random( )创建0-1之间的随机元素,数组包含的元素数量由参数决定;

    rand( ):根据给定维度生成[0,1)之间的数据;

    randn( ):返回一个或一组样本,具有标准正态分布N(0,1)

    randint( ):返回随机整数,最后一个参数是元组,他确定数组的形状

print(np.random.random(5))  # [0.34392369 0.7638822  0.93109906 0.4322686  0.39725031]
print(np.random.rand(5))    # [0.23784343 0.50962708 0.89161196 0.63161846 0.02673965]
print(np.random.randn(5))   # [ 0.56585504  1.39414002  1.0225824   1.62037609 -0.49034927]
print(np.random.randint(1, 5, (2, 3)))  # [[2 1 4] [4 1 4]] 

2 数组属性

  (1)ndim:数组维度数; 

  (2)shape:数组形状;

  (3)size:元素个数,等于shape中元组元素的乘积。

  (4)dtype:元素类型

a = np.array([[1, 2, 3], [4, 5, 6]])
print('数组的维度: ', a.ndim)    # 数组的维度:  2
print('数组的形状: ', a.shape)   # 数组的形状:  (2, 3)
print('数组的元素数量: ', a.size)  # 数组的元素数量:  6
print('数组的元素类型: ', a.dtype)     # 数组的元素类型:  int32

    2.1 更改数据类型

  创建Numpy数组的时候可以通过属性dtype显示指定数据类型,如果不指定的情况下,Numpy会自动推断出适合的数据类型,所以一般不需要显示给定数据类型。

a2 = np.array([[1, 2, 3], [4, 5, 6]], dtype=float)
print('数组a2的数据类型是:', a2.dtype)    # 数组a2的数据类型是: float64

  如果需要更改一个已经存在的数组的数据类型,可以通过astype方法进行修改从而得到一个新数组。

    2.2 更改数组形状

  对于一个已经存在的ndarray数组对象而言,可以通过修改形状相关的参数/方法从而改变数组的形状。

  (1)使用reshape函数更改原数组复制的形状, 创建一个改变尺寸的新数组,原数组的shape保持不变

a = np.arange(0, 20, 2)
print('原数组: \n', a)
# 原数组: # [ 0 2 4 6 8 10 12 14 16 18] b = a.reshape(2, 5) print('复制更改形状后的原数组:\n', a) print('复制更改形状后的复制数组:\n', b)
# 复制更改形状后的原数组: # [ 0 2 4 6 8 10 12 14 16 18] # 复制更改形状后的复制数组: # [[ 0 2 4 6 8] # [10 12 14 16 18]]

  但是新数组和原数组共享一个内存空间,修改任何一个数组中的值都会对另外一个产生影响,另外要求新数组的元素个数和原数组一致(还可以降维操作)。

b[0][1] = 50
print('更改元素后的原数组:\n', a)
print('更改元素后的复制数组:\n', b)
# 更改元素后的原数组: # [ 0 50 4 6 8 10 12 14 16 18] # 更改元素后的复制数组: # [[ 0 50 4 6 8] # [10 12 14 16 18]]

  (2)更改数组本身形状,直接修改数组ndarrayshape, 要求修改后乘积不变。

a.shape = (5, 2)
print('更改形状属性后的原数组:\n', a)
print('更改形状属性后的复制数组:\n', b)

# 更改形状属性后的原数组:
#  [[ 0 50]
#  [ 4  6]
#  [ 8 10]
#  [12 14]
#  [16 18]]
# 更改形状属性后的复制数组:
#  [[ 0 50  4  6  8]
#  [10 12 14 16 18]]

  当指定某一个轴为-1的时候,表示将根据数组元素的数量自动计算该轴的长度值。 

3 数组操作

    3.1 数组基本运算

  数组与标量:直接对数组元素操作

  数组与数组:大小相等的数组之间的运算,为元素级运算,即只用于位置相同的元素之间,所得的运算结果组成一个新的数组,运算结果的位置跟操作数位置相同。

a1 = np.array([[1, 2, 3], [4, 5, 6]])
a2 = np.array([[4.6, 3.2, 2.1], [5.2, 4.3, 3.4]])
print(a1+a2)
# [[5.6 5.2 5.1] # [9.2 9.3 9.4]]

  大小不等的数组之间先通过广播模式转换为大小相等的数组进行元素级操作。

a3 = np.array([10, 20, 30])
print(a1+a3)
# [[11 22 33] # [14 25 36]]

    3.2 数组的矩阵积

  多维数组即矩阵,两个二维矩阵(行和列的矩阵)满足第一个矩阵的列数与第二个矩阵的行数相同,那么可以进行矩阵的乘法,即矩阵积,矩阵积不是元素级的运算。也称为点积、数量积。

print("============点积:A*B,对应位置相乘===============")
A = np.array([[1, 1],
              [0, 1]])
B = np.array([[2, 0],
              [3, 4]])
print("A=\n", A)
print("B=\n", B)
print("A*B=\n", A*B)

# A.*B =[[1*2,1*0]
#        [0*3,1*4]]
#      =[[2,0]
#       [0,4]]

print("=============dot:矩阵相乘A.dot(B)===========")
print("-----书写格式1:A.dot(B)-----")
print(A.dot(B))

# A.dot(B)=[[1*2+1*3,1*0+1*4]
#           [0*2+1*3,0*0+1*4]]
#        =[[5,4]
#          [3,4]]

print("-----书写格式2:np.dot(A, B)-----")
print(np.dot(A, B))

# A.dot(B)=[[1*2+1*3,1*0+1*4]
#           [0*2+1*3,0*0+1*4]]
#         =[[5,4]
#           [3,4]]

     3.3 数组的索引

  (1)[idx1][idx2][idxn] 通过下标:

  (2)[strat:end:step]:单维切片,可直接使用冒号,不指定startend

  (3)[strat1:end1:step1, strat2:end2:step2, ...]:多个维度间用逗号隔开,“:”表示省略当前维度,“...”表示省略多个连续维度。

a = np.random.randint(1, 30, (2, 3, 5))
print(a[:, 2, 3].shape)     # (2,)  省略的维度
print(a[:, :, 1].shape)     # (2, 3) 省略的维度
print(a[1, ...].shape)      # (3, 5) 省略的维度
print(a[:, 2, 1:5].shape)   # (2, 4)
print(a[:, 0:2, 1:5].shape)     # (2, 2, 4) 省略的维度和某维度中所取维度

  Numpy中通过切片得到的新数组,只是原来数组的视图,因此对新数组的操作也会影响原数组。

a = np.array([
    [[1, 2, 3],
     [4, 5, 6]],

    [[1.1, 2.2, 3.3],
     [4.4, 5.5, 6.6]]
])
print(a.shape)      # (2, 2, 3)
print(a[1][0][2])   # 3.3
a[:, :, 1:3] = 10
print(a)
# [[[ 1.  10.  10. ]
#   [ 4.  10.  10. ]]
# 
#  [[ 1.1 10.  10. ]
#   [ 4.4 10.  10. ]]]

  (4)花式索引:利用整数数组索引,数组为具体数据的坐标

a = np.arange(32).reshape(8, 4)
print('花式索引获取0、3、5行数据:\n', a[[0, 3, 5]])
print('花式索引获取具体数据:\n', a[[0, 3, 5], [0, 2, 3]])

# 花式索引获取0、3、5行数据:
#  [[ 0  1  2  3]
#  [12 13 14 15]
#  [20 21 22 23]]
# 花式索引获取具体数据:
#  [ 0 14 23]

  (5)布尔索引:返回对应索引数组中数据为True位置的值组成的列表

a =np.array([
    [1, 2, 3],
    [4, 5, 6]
])
b = np.array([
    [True, False, False],
    [False, True, False]
])
print(a[b])     # [1 5]

    3.4 数组的转置与轴对换

  数组转置是指将shape值重置为原始shape元组的倒置,比如原始的shape值为:(2,3,4),那么转置后的新元组的shape的值为:(4,3,2)对于二维数组(矩阵),数组的转置(T属性)其实就是矩阵的转置,可以通过调用数组的transpose函数进行任意转置操作,参数为维度排列。

a = np.random.random((5, 4, 8, 2))
print(a.shape)      # (5, 4, 8, 2)
print(a.T.shape)    # (2, 8, 4, 5)
print(a.transpose(1, 3, 2, 0).shape)    # (4, 2, 8, 5) 

    3.5 数组的拉伸与合并

  (1)tile(arr,rep):将数组沿维度方向重复,第二个参数为不同维度重复次数组成的元组

  (2)stack(arr, axis=0):沿着新的轴加入一系列数组

  (3)vstack(arr1, arr2):堆栈数组垂直顺序(行)

  (4)hstack(arr1, arr2):堆栈数组水平顺序(列)

a = np.arange(6).reshape(2, 3)
b = np.arange(6, 12).reshape(2, 3)
print(a)
# [[0 1 2]
#  [3 4 5]]
print(b)
# [[ 6  7  8]
#  [ 9 10 11]]
print(np.tile(a, 2))    # 按维度拉伸
# [[0 1 2 0 1 2]
#  [3 4 5 3 4 5]]
print(np.tile(a, (2, 2)))   # 按维度拉伸(多维)
# [[0 1 2 0 1 2]
#  [3 4 5 3 4 5]
#  [0 1 2 0 1 2]
#  [3 4 5 3 4 5]]
print(np.stack((a, b), axis=1))  # 沿在第二维度添加并合并
# [[[ 0  1  2]
#   [ 6  7  8]]
# 
#  [[ 3  4  5]
#   [ 9 10 11]]]
print(np.vstack((a, b)))    # 垂直堆叠
# [[ 0  1  2]
#  [ 3  4  5]
#  [ 6  7  8]
#  [ 9 10 11]]
print(np.hstack((a, b)))    # 水平堆叠
# [[ 0  1  2  6  7  8]
#  [ 3  4  5  9 10 11]]

4 常用函数

  (1)通用函数:快速的元素级数组成函数,主要包括一元函数和二元函数。【该部分函数很多,主要靠平时积累】

  (2)聚合函数:默认对数组整体聚合,也可以指定轴操作,常见操作有:平均值、最大值、最小值、总体标准偏差等。

a = np.arange(12).reshape(3, 4)
print(a)
print('a.max(): ', a.max())     # 11
print('a.max(axis=0): ', a.max(axis=0))     # [ 8  9 10 11]
print('a.max(axis=1): ', a.max(axis=1))     # [ 3  7 11]
print('a.min(axis=1): ', a.min(axis=1))     # [0 4 8]
print('a.mean(axis=0): ', a.mean(axis=0))   # [4. 5. 6. 7.]
print('a.std(axis=1): ', a.std(axis=1))     # [1.11803399 1.11803399 1.11803399]
print('a.sum(): ', a.sum())     # 66

  (3)np.where(condition, x, y):是三元表达式x if condition else y的矢量化版本

arr = np.array([
    [1, 2, np.NaN, 4],
    [4, 5, 6, np.NaN],
    [7, 8, 9, np.inf],
    [np.inf, np.e, np.pi, 4]
])
condition = np.isnan(arr) | np.isinf(arr)
print('原始数组:\n', arr)
print('筛选结果:\n', np.where(condition, 0, arr))
# 原始数组:
#  [[1.         2.                nan 4.        ]
#  [4.         5.         6.                nan]
#  [7.         8.         9.                inf]
#  [       inf 2.71828183 3.14159265 4.        ]]
# 筛选结果:
#  [[1.         2.         0.         4.        ]
#  [4.         5.         6.         0.        ]
#  [7.         8.         9.         0.        ]
#  [0.         2.71828183 3.14159265 4.        ]]

  (4)np.unique( ):数组元素去重(也就是只保存不重复的数据)

a = np.array([2, 4, 8, 9, 4, 6, 2, 1])
print('原始数组:', a)   # [2 4 8 9 4 6 2 1]
print('去重后数组:', np.unique(a))   # [1 2 4 6 8 9]

猜你喜欢

转载自www.cnblogs.com/wisefaith/p/12274838.html