Python数据分析与挖掘
上QQ阅读APP看书,第一时间看更新

1.1 NumPy数组的创建与保存

创建NumPy数组一般有以下3种方法。

● 通过传入可迭代对象创建,这是基本方法。

● 使用NumPy内部功能函数创建,这是一种通用方法。

● 读取外部数据创建。

1.1.1 使用基本方法创建数组

基本方法是对已知可迭代对象创建ndarray数组,即通过在NumPy提供的array()方法中传入可迭代对象来创建数组。这种方法通常是在已知所有元素的情况下使用的。

基本方法的实现格式:np.array([可迭代对象])。

那什么是可迭代对象?Python可以对列表、元组、字典、字符串等类型的数据使用for...in...循环语法,从其中依次读取数据,我们把这样的过程称为遍历,也叫迭代。所以,我们把能够通过for...in...这类语句迭代读取一条条数据供用户使用的对象称为可迭代对象。

在NumPy中创建数组的基本方法如下。

【动动手练习1-1】 使用基本方法创建数组


>>>import numpy as np
>>> np.array([0, 1, 2, 3, 4])  #接收一个列表作为参数 
array([0, 1, 2, 3, 4]) 
>>> np.array([[11, 12, 13],[21, 22, 23]])  #创建一个2*3的二维数组 
array([[11, 12, 13], 
      [21, 22, 23]]) 
>>> np.array([[[1,2,3],[1,2,0]],[[5,6,7],[9,8,7]]])  #创建一个 2*2*3 的三维数组,可以将其理解为由两个或更多个二维数组组成三维数组。同样地,四维数组可以被理解为由两个或更多
个三维数组生成 
array([[[1, 2, 3], 
        [1, 2, 0]], 
       [[5, 6, 7], 
       [9, 8, 7]]]) 
>>> np.array((0, 1, 2, 3, 4))  #接收一个元组作为参数 
array([0, 1, 2, 3, 4]) 
#np.array()方法可以在创建数组的同时指定数据类型 
>>> np.array([0, 1, 2, 3, 4], dtype=float)  #注意数据类型使用dtype定义 
array([0., 1., 2., 3., 4.]) 
#还可以将创建整数列表的range()函数返回的可迭代对象作为参数 
>>> np.array(range(5)) 
array([0, 1, 2, 3, 4]) 
>>> np.array(range(10, 20, 2)) 
array([10, 12, 14, 16, 18]) 
>>>type(np.array(range(5)))  #查看变量类型 
numpy.ndarray

ndarray是同一个数据类型的数组,后面会有更详细的介绍。实现以下语句,查看返回的ndarray各元素的值。


np.array([0, 1, 2, 3, 4], dtype=str)
np.array([0, 1, 2, 3, 4], dtype=bool)

1.1.2 使用通用方法创建数组

通用方法指的是由NumPy提供的np.arange()、np.linspace()、np.ones()、np.zeros()、np.eye()、np.full()、np.random.random()、np.random.randint()方法直接生成数组。这些方法可以按照某种规则生成一个数组,并不需要传入已知的可迭代对象。

【动动手练习1-2】 使用通用方法创建数组

(1)np.arange()方法。

前面我们将range()函数的结果传递给np.array(),是对已知可迭代对象创建ndarray数组,这和NumPy中的np.arange()方法实现的功能是一样的。np.arange()方法是直接生成数组,可以说np.arange()方法就是NumPy中的range()方法。


>>> np.arange(5)
array([0, 1, 2, 3, 4]) 
>>> np.arange(10, 20, 2) 
array([10, 12, 14, 16, 18])

(2)np.linspace()方法。

np.linspace()方法以等间距的形式划分给定的数来创建数组。


>>> np.linspace(10, 20, 5)  #将10~20的数等距取5个
array([10. , 12.5, 15. , 17.5, 20. ])

(3)np.ones()方法。

np.ones()方法用于创建一个元素值全为1的数组,接收一个列表或者元组作为参数,这些参数决定创建数组的维数。


>>> np.ones([2]) #创建一个一维数组
array([1., 1.]) 
>>> np.ones([2, 2])  #创建一个二维数组 
array([[1., 1.], 
    [1., 1.]]) 
>>>np.ones([2, 3, 3],dtype=int)  #创建一个三维数组,该数组由2个3*3的二维数组组成 
array([[[1, 1, 1], 
        [1, 1, 1], 
        [1, 1, 1]], 
       [[1, 1, 1], 
        [1, 1, 1], 
        [1, 1, 1]]])

(4)np.zeros()方法。

np.zeros()方法用于创建一个元素值全为0的数组,接收一个列表或者元组作为参数。


>>> np.zeros([3])  #创建一个一维数组,参数是一个列表[3]
array([0., 0., 0.]) 
>>> np.zeros((3, 3))  #创建一个二维数组,参数是一个元组(3, 3) 
array([[0., 0., 0.], 
    [0., 0., 0.], 
    [0., 0., 0.]])

(5)np.eye()方法。

np.eye()方法用于创建一个从左上角到右下角的对角线上的元素值全为1,其余元素值全为0的数组(单位矩阵)。注意,np.eye()方法的参数可不再是列表或者元组了。


>>> np.eye(3, 3)  #注意np.eye()方法与np.zeros()、np.ones()方法参数的区别,np.eye()方法的参数是两个数值
array([[1., 0., 0.], 
    [0., 1., 0.], 
    [0., 0., 1.]]) 
>>> np.eye(2, 3) 
array([[1., 0., 0.], 
        [0., 1., 0.]])

可以将对称的矩阵(如上面的np.eye(3, 3))简写为np.eye(3),其结果是相同的。

当然,以上生成数组的数值类型默认是浮点型,如果设置为其他数值类型可使用dtype定义。

(6)np.full()方法。

np.full()方法可以创建一个填充给定数值的数组。数组由两个参数组成:第1个参数是定义数组形状的列表或元组,第2个参数是需要填充的数值。


>>> np.full((2, 3), 3)  #创建一个2*3的数组,所有元素都填充3
array([[3, 3, 3], 
    [3, 3, 3]])

(7)np.random.random()方法。

np.random.random()方法用于创建一个元素值为0~1的随机数数组,接收一个列表或者元组作为参数。


>>> np.random.random((3, 3))  #创建一个3行3列的二维数组
array([[0.19414645, 0.2306415 , 0.08072019],  #数组元素是随机产生的 
    [0.68814308, 0.48019088, 0.61438206], 
    [0.5361477 , 0.33779769, 0.38549407]])

(8)np.random.randint()方法。

既然有np.random.random()方法,就会有np.random.randint()方法,也就是取随机整数的方法。不过这个np.random.randint()方法参数的形式与Python的random.random()不太一样,具体请看下面的实例。


>>>import random
>>>random.random()        #取0~1的随机数 
0.4481402883460749 
>>>random.randint(10,20)  #取10~20的随机整数 
15 
#注意np.random.randint()方法与Python的random.random()方法的异同 
>>> np.random.randint(1, 10, 3)  #从1~10中随机取3个整数创建一维数组 
array([6, 4, 6]) 
>>> np.random.randint(1, 10,(2,3))    #创建2行3列的二维数组,参数(2,3)是数组形状 
array([[7, 4, 3], 
      [9, 1, 6]]) 

数组形状就是数组的维数。事实上,比较np.random.randint()方法与Python的random.random()方法,我们就会发现,Python的random.random()方法主要是实现一个随机数,而np.random.randint()方法是一次生成一个数组的随机数,并且可以定义不同的数组形状。

1.1.3 读取外部数据创建数组

数据分析离不开对数据的获取,NumPy也支持从外部读取数据来创建数组,例如从硬盘中读取CSV、TXT等文本文件来创建数组。np.loadtxt()是NumPy中读取文件的一个方法(NumPy还有其他读文件的方法,本书只介绍该方法),其一般用法:np.loadtxt(fname, dtype=<class 'float'>, comments='#', delimiter=None, converters=None, skiprows=0,usecols=None, unpack=False)。

各参数说明如下。

● fname:要读取的文件、文件名或生成器。

● dtype:数据类型,默认为浮点型。

● comments:注释,默认是#。

● delimiter:分隔符,默认是空格。

● converters:转换器,可以对读入的数据设置转换操作,一般与转换函数配合使用。

● skiprows:跳过前几行读取,默认是0,必须是整型。

● usecols:要读取哪些列,0是第1列。例如,usecols = (1,4,5)将提取第2、5和6列。默认读取所有列。

● unpack:如果为True,将分列读取,有多少列就返回多少个向量数组;如果为默认的False,则分行读取,将读取的列合并为一个向量元素。

上面给出了np.loadtxt()方法所有的关键字参数,下面我们只对感兴趣的参数给出示例。

【动动手练习1-3】 读取外部数据创建NumPy数组

在d盘的data目录下创建一个id.csv文件,文件内容如下。(表示路径的方式有“/”和“\\”两种,本书统一采用“\\”)


id,height,length
1,100,101 
2,200,230 
3,300,350

通过NumPy读取数据。


>>> np.loadtxt('d:\\data\\id.csv',delimiter=',',skiprows=1)  #也可以写成
#np.loadtxt(fname='d:\\data\\id.csv',delimiter=',',skiprows=1) 
array([[  1., 100., 101.],  #按行输出 
      [  2., 200., 230.], 
      [  3., 300., 350.]]) 
>>>np.loadtxt('d:\\data\\id.csv',delimiter=',',skiprows=1,unpack=True)# 增加unpack参数 
array([[  1.,   2.,   3.],  #按列输出,一列为一维 
      [100., 200., 300.], 
      [101., 230., 350.]])

第1个参数fname为'd:\\data\\id.csv',是读取的文件名称。

第2个参数delimiter是指定读取文件中数据的分割符。

第3个参数skiprows是选择跳过的行数。

我们可以比较unpack参数的作用,默认行数据为数组元素。将其值设为True,则按列输出。

读取外部数据的方法还有np.genfromtxt()等,在此不再介绍,读者可自行查阅相关知识学习。

1.1.4 将数组保存为文本文件

np.savetxt()方法需要2个参数:第1个参数是文件名,数据类型为字符串;第2个参数是被写入文件的数据,数据类型为ndarray对象。

需要说明的是,写入的ndarray数组元素数据为字符串内容时,写入会出错。这是因为NumPy是一个数学计算包,侧重数值的处理,只能写入数值数据。另外,使用NumPy可直接导入数值数据,但读字符串会出错,如果必须读入文本数据,一般会使用转换器对应的函数将文本转换为数值。

下面举例说明使用np.savetxt()方法写入文本文件。

【例题1-1】 将NumPy数组保存为文件


>>>import numpy as np
>>> matrix=np.eye(2).astype('int')      #生成对称矩阵二维数组,并将其值转换为整数 
>>> matrix                 #查看矩阵数组 
array([[1, 0],             #显示结果 
      [0, 1]]) 
>>> matrix.dtype           #查看矩阵二维数组的数据类型 
dtype('int32')             #显示为32位的整数 
>>> np.savetxt('d:\\data\\eys.txt',matrix)   #使用np.savetxt()方法写入文本文件

写入文本文件的结果如图1-1所示。

图1-1 使用np.savetxt()方法写入文本文件的结果

从图1-1可以看出,ndarray对象中的元素数据类型原本为整型,但写入文件时转变为浮点型。同样,使用np.loadtxt()方法载入数据时,即使原来文本中数据的类型为整型,载入后转换为ndarray数组的数据类型也会默认变成浮点型,读者可自行试验。