python 数据分析(二)numpy模块详解 + numpy的使用 + 使用numpy属性创建数组 + numpy.random相关方法 + 数据类型 + 数组元素访问 + 数组操作(变换展平组合)

文章目录

一、Numpy

1. numpy的介绍


NumPy是使用Python进行科学计算的基本软件包。它包含以下内容:

NumPy已获得BSD许可证的许可,从而可以无限制地进行重用。

  • 介绍
    一个用python实现的科学计算,
    包括:
    • (1)强大的N维数组对象
    • (2)复杂的(广播)功能
    • (3)集成C / C ++和Fortran代码的工具
    • (4)有用的线性代数,傅立叶变换和随机数功能
    • (5)除了其明显的科学用途外,NumPy还可以用作通用数据的高效多维容器。可以定义任意数据类型。这使NumPy可以无缝,快速地与各种数据库集成。

NumPy(Numeric Python)提供了许多高级的数值编程工具,如:矩阵数据类型、矢量处理,以及精密的运算库。专为进行严格的数字处理而产生。多为很多大型金融公司使用,以及核心的科学计算组织如:Lawrence Livermore,NASA用其处理一些本来使用C++,Fortran或Matlab等所做的任务。

  • 作用:NumPy系统是Python的一种开源的数值计算扩展。这种工具可用来存储和处理大型矩阵,比Python自身的嵌套列表(nested list structure)结构要高效的多(该结构也可以用来表示矩阵(matrix))。

  • 作用对象:numpy的主要对象是同种元素的多维数组

numpy内置了并行运算功能,当系统有多个核心时,做某种计算时,numpy会自动做并行计算。
Numpy底层使用C语言编写,数组中直接存储对象,而不是存储对象指针,所以其运算效率远高于纯Python代码。


2. 数组和列表的区别


  • 相同:结构:[元素1,元素2,元素。。。。]

  • 不同的是叫法:

    数组:C语言、Java

    列表:只有python叫列表

python下的列表可以放任何东西:[‘123’,456,True,xiaoming] (存储任何类型的都可以,要多次判断,所以效率慢)

C语言下的数组存储相同类型的数据

int a[10] ------>只能存数值,所以效率快

a[0] = 1

a[1]=‘123’ #报错


3. numpy使用python的原因


python的特点:python这门语言代码执行效率低,编程效率高

但Numpy底层是C语言实现的,执行效率高,解决了这一问题

数组的叫法就是因为底层是C语言写的


4. Numpy的使用(数组中的用法)


① 第一步:导包

import numpy

② 创建一个数组


一维数组:

arr1 = numpy.array([1,2,3])

③ 数组的常用属性


  • 轴 (axes) ---- 维度 — 几行几列
  • 秩(rank)----- 轴的个数

(1)维度:shape


  • 代码:
    # 一维数组
    arr1 = numpy.array([1,2,3])
    # ## 输出轴 --- 维度shape
    print(arr1.shape) ## 数组的形状  (3,)----》元组,一维,行和列的写法
    # # 二维数组
    arr2 = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
    print(arr2.shape)  # (3, 3)
    

注意:一维数组打印的是列数(每行的元素个数) 我们可以理解为返回的是元素的个数

  • 案例演示:
    在这里插入图片描述
    注意:二维数组,元祖中第一个参数是行数,第二个是列数(每行的元素个数)
    在这里插入图片描述

(2)秩:ndim


  • 代码:
    # ## 输出秩 --- ndim
    arr1 = numpy.array([1,2,3])
    arr2 = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
    print("arr1的秩:",arr1.ndim) # arr1的秩: 1  --- 元组中数的个数,如(3,)
    print("arr2的秩:",arr2.ndim) # arr2的秩: 2
    ## 秩的另一种求法
    print(len(arr2.shape))
    

tip:秩可以用本身的ndim方法来获取,也可以用len(arr.shape)来获取

  • 案例演示:
    在这里插入图片描述

(3)数组元素总个数:size


size方法所存在的意义就是获取数组中元素的总个数

  • 代码:

    arr3 = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
    print(arr3.shape)
    print(arr3.ndim)
    print(len(arr3.shape))
    
    # 数组元素总个数:size
    print("数组元素的总个数:",arr3.size)  #数组元素的总个数: 9
    
  • 案例演示:
    在这里插入图片描述


(4)数组的元素类型:dtype


  • 代码:
    arr3 = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
    # 数组元素的类型:dtype  int32  表示整型32位
    print("数组元素的类型",arr3.dtype) # 数组元素的类型 int32
    
  • 案例演示:
    在这里插入图片描述
    在这里插入图片描述

跟存入的数据有关,数组没有指定的时候默认就用自己的类型


(5)每个元素的字节大小:itemsize


  • 代码:

    # # 每个元素的字节大小:itemsize
    # ## 字节(byte)-----位(bit)
    # # 8bit = 1byte
    arr3 = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
    print(arr3.dtype) # int32
    print("arr3每个元素的字节大小",arr3.itemsize)  # arr3每个元素的字节大小 4
    
  • 案例演示:
    在这里插入图片描述


(6)缓冲区:data


  • 代码

    arr3 = numpy.array([[1,2,3],[4,5,6],[7,8,9]])
    print(arr3.data)  # <memory at 0x0000000003149C18>
    
  • 案例演示:
    在这里插入图片描述

注意:缓冲区时刻在变化


二、使用numpy的属性创建数组


1. numpy.array()创建数组


使用array()函数

```python
def array(p_object, dtype=None, copy=True, order='K', subok=False, ndmin=0)
# p_object:接收一个array,eg:[1,2,3]  ## numpy.array([1,2,3])
# dtype:接收一个data-type类型,表示数组所需要的数据类型;默认为空,如果没有给定,则根据传入元素,指定所需要的一个最小的数据类型;int32,int64
```
  • 代码:

    arr1 = numpy.array([1,2,3,4])
    arr2 = numpy.array([[1,2],[3,4]])
    arr3 = numpy.array([(1,2),(3,4)])
    print("arr1:",arr1)
    print("arr2:",arr2)
    print("arr3:",arr3)
    
    arr4 = numpy.array([1,2,3,4],dtype=numpy.float64)
    print(arr4)
    
  • 案例演示:
    在这里插入图片描述


2. 使用numpy.arange()


  • 代码:

    # def arange(start=None, stop=None, step=None, dtype=None)
    arr5 = numpy.arange(0,1,0.1)  ## 区间前闭后开
    print(arr5) # [ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9]
    
  • 案例演示:
    在这里插入图片描述

注意:该区间是前闭后开的


3. 使用numpy.linspace()


  • 代码:

    # def linspace(start, stop, num=50, endpoint=True, retstep=False, dtype=None)
    arr6 = numpy.linspace(0.1,1,10)  # 闭合区间:前后都是闭合的,第一个参数:开始;第二个参数:结束,第三个参数:生成多少个数
    print(arr6)  # [ 0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1. ]
    
  • 案例演示:
    在这里插入图片描述

注意:该区间前后都是闭合的

上面的两种都是等差数列


4. 使用numpy.logspace() -----> 等比数列


  • 代码:

    ## 4. 使用logspace() -----> 等比数列
    # logspace(start, stop, num=50, endpoint=True, base=10.0, dtype=None)
    arr7 = numpy.logspace(1,3,3) # [   10.   100.  1000.]
    # 第三个参数为生成几个数
    print(arr7)
    arr8 = numpy.logspace(1,10,10,base=2)
    # 第一个参数:2的一次方,第二个参数:2的10次方,第三个参数:生成几个数
    print(arr8) # [    2.     4.     8.    16.    32.    64.   128.   256.   512.  1024.]
    
  • 案例演示:
    在这里插入图片描述


5. 使用numpy.zeros() 全0数组


  • 代码:

    ## 5. 使用zeros() 全0数组
    # def zeros(shape, dtype=None, order='C')
    arr9 = numpy.zeros((3,3))
    print(arr9)
    
  • 案例演示:
    在这里插入图片描述

注意:shape代表的是数组的维度(通俗来说就是几行几列)


6. 使用numpy.ones() ---- 全1数组


  • 代码:

    print(numpy.ones((2,3)))
    
  • 案例演示:
    在这里插入图片描述


7. 使用numpy.empty() ---- 创建一个内容随机,并且依赖于内存状态的数组


  • 代码:

    ## 7. 使用empty() ---- 创建一个内容随机,并且依赖于内存状态的数组
    # def empty(shape, dtype=None, order='C')
    print("empty:",numpy.empty((2,3)))
    
  • 案例演示:
    在这里插入图片描述
    在这里插入图片描述

注意:该方法创建数组要注意内存中是否存留状态,如上面的例子一样,会有不同结果


8. 使用numpy.eye()


关注第一个第三个参数就行了

第一个参数:输出方阵(行数=列数)的规模,即行数或列数,在默认第二个参数为None的情况下

第三个参数:默认情况下输出的是对角线全“1”,其余全“0”的方阵,如果k为正整数,则在右上方第k条对角线全“1”其余全“0”,k为负整数则在左下方第k条对角线全“1”其余全“0”。

  • 代码:

    ## 8. 使用eye()
    # def eye(N, M=None, k=0, dtype=float)
    arr10 = numpy.eye(3)
    print(arr10) ## n阶矩阵
    arr10 = numpy.eye(3,k=2)
    print(arr10) ## n阶矩阵
    arr10 = numpy.eye(3,k=-2)
    print(arr10) ## n阶矩阵
    
  • 案例演示:
    在这里插入图片描述


9. 使用 numpy.diag()


以一维数组的形式返回方阵的对角线(或非对角线)元素,或将一维数组转换成方阵(非对角线元素为0).两种功能角色转变取决于输入的v。

v : array_like.
如果v是2D数组,返回k位置的对角线。

如果v是1D数组,返回一个v作为k位置对角线的2维数组。

k : int, optional
对角线的位置,大于零位于对角线上面,小于零则在下面。

在这里插入图片描述
在这里插入图片描述


10. 练习(shape方法和reshape()方法更改数组维度)


## 要求生成一个3X5的一个数组,数组元素为0~14之间的整数
import numpy
arr = numpy.arange(0,15)
# 通过赋值shape属性更改数组的维度
arr.shape = (3,5)
print(arr)
# 通过使用reshape()
arr2 = arr.reshape(3,5)
print(arr2)

在这里插入图片描述


三、numpy.random的相关方法


import numpy
# 生成随机数组
1. random.random(n) ----- 值域:[0,1)  , n表示元素的个数
arr1 = numpy.random.random(3)  ## 参数是多少个随机数
print(arr1)

arr2 = numpy.random.random(15).reshape(3,5)  ## 生成3行5列的数组
print(arr2)

2. random.rand(m,n)  ## 生成一个mXnXp ..... 多维数组;值域:[0,1)
arr3 = numpy.random.rand(2,3)
print(arr3)

3. random.randn()  ## 生成正态随机数

arr4 = numpy.random.randn(3) # 参数,生成多少个符合正态分布的数
print(arr4) # [-0.04022466  0.89657514  0.23527142]

常识 ----大数定理
# 画图
import matplotlib.pyplot as plt
plt.hist(arr4)
plt.show()

4. random.randint() # 闭合区间[a,b],eg: a<=value<=b
def randint(low, high=None, size=None, dtype='l') # size 要么整型,要么整型的元组,输出几行几列
arr5 = numpy.random.randint(1,10,size=(2,5))
print(arr5)

5. random模块常用的随机生成函数
# normal:产生正态(高斯)分布的随机数
# beta:产生beta分布的随机数
# chisquare:产生卡方分布的随机数
# gamma:产生gamma分布的随机数

在这里插入图片描述
上面的情况是数据太少,所以没显示正态分布
下面是增加后
在这里插入图片描述


四、数据类型


注意:所有非零数据转换成bool类型都是True,零转换的都是False

################### 一、基本数据类型####################

## 1. bool
## 2. inti  后面的i 为多少位 如 32,64

################## 二、数据类型的转换###################
print(np.float64(42))

# np.int32(42.0)
########## 所有非零数据转换成bool类型都是True,零转换的都是False
print(np.bool(42))
print(np.bool(0))

在这里插入图片描述
要注意的是自定义类型

#################### 三、定义数据类型####################
##eg:创建一个存储餐饮企业库存信息的数据类型

# 规定:
# (1)用一个长度为40的字符串来记录商品的名称
# (2)用一个64位的整数来记录商品的库存
# (3)用一个64位单精度浮点记录商品的价格

## 第一个是字段名,第二个是类型,第三个是多少位
df = np.dtype([('name',np.str_,40),('numitems',np.int64),('price',np.float64)])  ## 是一个方法,可以定义数据类型
print('df数据类型:',df) # df数据类型: [('name', '<U40'), ('numitems', '<i8'), ('price', '<f8')] # <U 小于U,U是unique

table = np.array([('beef',40000,4.14),('chicken',20,1.72)],dtype=df)
print(table)
print(table[0],type(table[0])) # ('beef', 40000,  4.14) <class 'numpy.void'> numpy.void 表明是自己定义的,它不能识别:无效的
print(table[0][1],type(table[0][1]))  ## 典型特点:速度快

在这里插入图片描述
注意:自定义的数组要在后面加自己写好的dtype


五、数组元素的访问


1. 通过索引来访问数组元素


  • 一维数组
    在这里插入图片描述
    在这里插入图片描述

2. 数组的切片和步长


在这里插入图片描述
注意:从后向前利用切片取数组的元素时,步长为负


3. 通过格式:数组名[行索引,列索引]访问元素


在这里插入图片描述


4. 通过格式:数组名[(行下标),(列下标)]访问元素


在这里插入图片描述
注意:行下标可指定,但列下标一定要和行下标一一对应;或者一个行下标对应多个列下标;或者多个行下标,对应:,获取该行所有元素

特例:定义好了结构,直接可以通过结构获取

df = numpy.dtype([('name',numpy.str_,40),('numitems',numpy.int64),('price',numpy.float64)])
table = numpy.array([('beef',40000,4.14),('chicken',20,1.72)],dtype=df)
print(table)
print(table['name'])

在这里插入图片描述


5. 遮罩mask


三、遮罩mask
arr3 = numpy.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
mask = numpy.array([1,0,1],dtype=numpy.bool) ## bool值代表是否显示
print(mask) # [ True False  True] True显示,False不显示
print(arr3[mask,2]) # [ 3 11]
print(arr3[(1,0,1),2]) # [7 3 7]

在这里插入图片描述

注意:遮罩其含义就是通过使用bool的True和False来展示我们想要显示的数据


六、数组的操作(变换,展平,组合)


1. shape和reshape()-------数组变化


在上面提到的两种变换数组形态的方法

## 要求生成一个3X5的一个数组,数组元素为0~14之间的整数
import numpy
arr = numpy.arange(0,15)
# 通过赋值shape属性更改数组的维度
arr.shape = (3,5)
print(arr)
# 通过使用reshape()
arr2 = arr.reshape(3,5)
print(arr2)

2. 展平数组


(1)ravel()


  • 代码:
# (1) ravel()
# 说明:是reshape函数的逆操作
# 注意:并不修改原数组,而是创建了一个新数组

arr1 = numpy.arange(10000)
arr2 = arr1.reshape((100,100))
print(arr1)
print(arr2)
arr3 = arr2.ravel()
print("arr3:",arr3) # [   0    1    2 ..., 9997 9998 9999]
  • 案例演示:
    在这里插入图片描述

注意:ravel()是reshape()函数的逆操作,并不修改原数组,而是创建了一个新数组

小知识:将中间省略的部分展开
格式numpy.set_printoptions(threshold=numpy.NaN)

借用上面的代码来实现:

arr1 = numpy.arange(10000)
arr2 = arr1.reshape((100,100))
# print(arr1)
# print(arr2)
arr3 = arr2.ravel()
print("arr3:",arr3) # [   0    1    2 ..., 9997 9998 9999]

# # tip1: 如果输出的数组数据量太大,在输出时,numpy自动省略中间部分,而只打印两边元素
# # 如果不需要省略,在打印之前设置如下信息:
numpy.set_printoptions(threshold=numpy.NaN)
print(arr2)
  • 案例演示:
    在这里插入图片描述

(2) flatten()


  • 代码:
arr4 = numpy.arange(10).reshape((2,5))
arr5 = arr4.flatten()
print("arr5:",arr5)
  • 案例演示:
    在这里插入图片描述

从上面看来,flatten也是展平数组的效果


(3)ravel()和flatten()的区别


  • 对一个数组展平的效果来说无区别
    在这里插入图片描述

共同点:都是将多维数组降为一维

区别:

  • 返回的是拷贝(copy):强调的是数据 ------- 使用flatten返回的是一份拷贝
  • 返回的是视图(view):侧重的是展现,而不是数据本身 ------- 使用ravel返回的是一份视图

案例演示:

  • 代码:

    a1 = numpy.array([[1,2],[3,4]])
    f_a = a1.flatten()
    r_a = a1.ravel()
    print("a1改动前:",a1)
    print("f_a",f_a) # f_a [1 2 3 4]
    print("r_a",r_a) # r_a [1 2 3 4]
    f_a[2] = 100
    print("flatten2:",f_a) # flatten2: [  1   2 100   4]
    print("f_a改动后",a1) ## flatten元素变化不影响原数组
    # f_a改动后 [[1 2]
    #  [3 4]]
    
    r_a[2] = 101
    print("r_a改动后",r_a) # r_a改动后 [  1   2 101   4]
    print("r_a改动后的a1",a1)  # 如果是ravel的数组元素发生更改,原数据同时也会发生改变
    
  • 结果:
    在这里插入图片描述

总结:flatten()在展平后修改数据,原数组不会改变,其相当于copy了数组;ravel()展平数组后修改数据,原数组会随之改变,其相当于view,数据只是拿数组的数据来展示。


3. 组合/切割数组


① 组合数组


(1)hstask() 和 vstack()


  • 代码:
### (1)hstask() 和 vstack()
arr1 = numpy.arange(1,6,2)
arr2 = numpy.arange(7,12,2)
print(arr1,arr2) # [1 3 5] [ 7  9 11]

arr3 = numpy.hstack((arr1,arr2)) ## 横向拼接(按行拼接)
print(arr3) # [ 1  3  5  7  9 11]
arr4 = numpy.vstack((arr1,arr2))
print(arr4) ## 纵向拼接 相当于将两个一维数组拼接成一个新的二维数组
  • 案例演示:
    在这里插入图片描述

注意:横向拼接(按行拼接),两个一维数组的话拼接后还是一维数组;纵向拼接 相当于将两个一维数组拼接成一个新的二维数组


(2)在组合数组时注意项


  • 如果两个数组元素个数不相等,横向能够拼接,但纵向将会报错

    arr1 = numpy.array([1,2])
    arr2 = numpy.array([3,4,5])
    arr3 = numpy.hstack((arr1,arr2))
    print(arr3) # [1 2 3 4 5]
    arr4 = numpy.vstack((arr2,arr1))
    print(arr4)  ## 报错
    

    在这里插入图片描述

  • 在stack函数(hstack和vstack)中,参数列表和元组都可以

    arr1 = numpy.array([1,2])
    arr2 = numpy.array([3,4,5])
    arr4 = numpy.hstack([arr1,arr2])
    print(arr4) # [1 2 3 4 5]
    arr5 = numpy.hstack([(6,6,6),(8,8,8,8)])
    print(arr5)
    

    在这里插入图片描述


② 组合数组:concatenate() 接收两个参数:函数和轴


(1)横向


  • 方法一:

    
    arr1 = numpy.array([[1,1],[2,2]])
    arr2 = numpy.array([[3,3],[4,4]])
    print(arr1)
    # # [[1 1]
    # #  [2 2]]
    print(arr2)
    # # [[3 3]
    # #  [4 4]]
    
    # ## 横向
    ## 方法1:
    print(numpy.hstack([arr1,arr2]))
    

    在这里插入图片描述

  • 方法二:

    print(numpy.concatenate((arr1,arr2),axis=1))
    

    在这里插入图片描述

结论:concatenate方法传参axis=1和hstack方法结果一样


(2)纵向


  • 方法一:

    print(numpy.vstack([arr1,arr2]))
    

    在这里插入图片描述

  • 方法二:

    print(numpy.concatenate((arr1,arr2),axis=0))
    

    在这里插入图片描述

结论:concatenate方法传参axis=0和vstack方法结果一样


七、order : {‘C’, ‘F’}问题


  • 首先要了解的是:order参数的C和F是numpy中数组元素存储区域的两种排列格式,即C语言格式和Fortran语言格式。
  • 主要区别: 所谓的Row major order和Column-major order 的区别,主要看你拿这数组作什么运算,如果是要依次访问每列的元素,Fortran Order(即Column-major order)下每列在内存中是连续的,这种结构相对更加Cache-friendly。这并不是编程语言自身的特性,在C语言中完全可以使用Column-major order,只不过访问起来计算index不太习惯而已。Fortran大概是因为主要用于科学计算,Column-major order对于一些矩阵运算有性能优势。

简单点来说就是order='C’支持索引;order='F’是顺序访问每列元素

案例:

  • order='C’创建一个3×3的2维数组

    import numpy as np
    a = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float32,order='C')
    

    数组a在内存中的数据存储区域中存储方式(默认order=“C”,其中一个格子是4bytes):

    |1|2|3|4|5|6|7|8|9|
    

    在C语言中当第一维数组也就是第0轴的下标增加1时,元素在内存中的地址增加3个元素的字节数,在此例中也就是12bytes,从1的地址增加12bytes到4的地址。此时

    a.strides = (12, 4)
    
  • 若以F order创建数组:

    b = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float32, order="F")
    

    数组b在内存中的数据存储区域中的存储方式:

    |1|4|7|2|5|8|3|6|9|
    

    在Fortran语言中,第一维也就是第0轴下标增加1时,元素的地址增加一个元素字节数,在此例子中也就是4 bytes,从1的地址增加4bytes到4的地址。

    b.strides = (4, 12)
    

简洁代码:

# F参数
# 'C'meanstoflatten in row - major(C - style)order. “C”意为按C大调(C调)顺序变平。
# 'F'meanstoflatten in column - major(Fortran -style)order “F”的意思是按列大调(Fortran风格)顺序变平
a2 = numpy.array([[1,2,3],[4,5,6]])
f_a = a2.flatten(order = 'F') # 按列展平
print("F_A",f_a) # F_A [1 4 2 5 3 6]
c_a = a2.flatten(order = 'C') # 按列展平
print("C_A",c_a) # C_A [1 2 3 4 5 6]

在这里插入图片描述


八、数组的arr5[0]的理解


地址:0x0000000003149C18; 别名:arr5

arr5[2]代表跨几个存储空间 ,一开始arr5代表最底层的存储空间,不用跨即可取到所以为[0]

在这里插入图片描述


发布了107 篇原创文章 · 获赞 43 · 访问量 6166

猜你喜欢

转载自blog.csdn.net/langdei/article/details/103093377