本篇博客所有示例使用Jupyter NoteBook演示。

Python数据分析系列笔记基于:利用Python进行数据分析(第2版)  

 

目录

1.ndarray对象简介

2.创建ndarray

3.ndarray的数据类型

4.ndarray对象的内部机理

5.NumPy数据类型体系


1.ndarray对象简介

NumPy最重要的一个特点就是其N维数组对象(ndarray),该对象是一个快速而灵活的大数据集容器。你可以利用这种数组对整块数据执行一些数学运算,即整个数组进行某种运算相当于对数组中的每个元素进行相同的运算(向量化运算),和标量元素间的运算语法是一样的。

下面直观理解NumPy是如何利用与标量值类似的语法进行批次运算的:

import numpy as np

data = np.random.randn(2,3)   #生成一个2*3的2维随机数组  randn随机值符合正太分布
print(data)

print(data*10)   #对数组*10  相当于对数组中的每个元素都*10  其他类似的运算同理
print(data+data)  #数组中的每个元素加上自身

python构造多维数组 python中的多维数组_ndarray

标准的NumPy用法是 import numpy as np,当然也可以使用 from numpy import *,但是不建议这么做。因为numpy的命名空间很大,包含许多函数,其中一些函数名字可能与Python内置的函数名相同,比如min,max等函数。为了区别,max()指的是Python内置的函数,而np.max()指的是numpy中内置的函数。

  • 数组的属性

ndarray是一个通用的同构数据多维容器,也就是说,其中的所有元素必须是相同类型的。

每个数组都有一个shape属性,一个用于表示数组各个维度大小的元组;还有一个dtype属性,用于说明数组中元素的数据类型。

print(data.shape)  #2维数组 第一个维度大小为2 第二个维度大小为3
print(data.dtype)  #数组中元素的数据类型

python构造多维数组 python中的多维数组_Python数组_02

Python数据分析系列博客,将会用多个篇幅来介绍NumPy数组的基本用法,对之后pandas数据分析打基础。虽然大多数数据分析工作不需要深入理解NumPy,但是精通面相数组的编程和思维方式是成为Python科学计算大牛的关键步骤。

本系列博客的‘数组’,‘NumPy数组’,‘ndarray’基本上指的都是一样东西,即ndarray对象。

2.创建ndarray

  • array函数

创建数组最简单的办法是使用array函数。他可以接受一切序列型的对象(包括列表,其他数组等),然后产生一个新的含有输入数据的NumPy数组:

data1 = [6,7.5,8,0,1]
arr1 = np.array(data1)  #以列表为输入 生成一维数组
print(arr1)
print("----------------------------")

data2 = [[1,2,3,4],[5,6,7,8]]  #嵌套序列  由等长列表组成的列表
arr2 = np.array(data2)  #以嵌套列表为输入   生成多维数组
print(arr2)
print("------------------------------")
#arr2的ndim和shape属性值 都来自于列表data2
print(arr2.ndim)  #查看数组的维度   
print(arr2.shape)  #查看数组每个维度的大小 返回一个元组

python构造多维数组 python中的多维数组_Python数据分析_03

除非特别指定(下一小节详细介绍),np.array会自动为新建的数组推断出一个适合的数据类型。数据类型保存在一个特殊的dtype对象中:

print(arr1.dtype)
print(arr2.dtype)

python构造多维数组 python中的多维数组_dtype_04

  • 其他创建数组的函数

除了np.array之外,还有一些函数可以创建数组。比如zeros和ones分别可以创建指定形状或长度的全0或全1的数组。empty可以创建一个没有任何具体值的数组。用这些方法创建多维数组,只需要传入一个表示形状的元组即可:

print(np.zeros(10))   #创建一个长度为10的一维数组  值全为0
print(np.zeros((3,6))) #创建一个3*6的2维数组  值全为0
print(np.empty((2,3,4)))  #创建一个2*3*4的3维空数组

python构造多维数组 python中的多维数组_Python数组_05

认为np.empty会返回全0数组的想法是不安全的。很多情况下,它会返回一些未初始化的垃圾值。

  • arange函数

arange函数是Python内置的range函数的数组版本:

print(np.arange(15))  #生成一个长度为15的一维数组 值0-14

python构造多维数组 python中的多维数组_ndarray_06

  • 其他创建数组的函数

由于NumPy关注的是数值计算,因此,如果没有特别指定,会自动会创建的数组推断出一个合适的数据类型(dtype)

python构造多维数组 python中的多维数组_Python数据分析_07

3.ndarray的数据类型

dtype(数据类型)是一个特殊的对象,它将ndarray的一块内存解释为特定数据类型所需要的信息。

arr1 = np.array([1,2,3],dtype='float64')
arr2 = np.array([1,2,3],dtype='int32')
'''
arr1 = np.array([1,2,3],dtype=np.float64)
arr2 = np.array([1,2,3],dtype=np.int32)
'''
print(arr1.dtype)
print(arr2.dtype)

python构造多维数组 python中的多维数组_python构造多维数组_08

创建数组时可以使用dtype=指定数据类型,不使用的话,会自动为数组推断出一个合适的数据类型.

dtype是NumPy灵活交互其他系统的源泉之一。多数情况下,他们直接映射到相应的机器表示,这使得“读写磁盘上的二进制数据流”以及“集成低级语言代码(如C、fortran)”等工作变得更加简单。数值型dtype的命名方式相同:一个类型名(如float或int),后面跟一个用于表示各元素位长的数字。标准的双精度浮点值(即Python中的float对象)需要占用8字节(64位)。因此,该类型在NumPy中就记做float64.

下表列出了NumPy所支持的全部数据类型:

python构造多维数组 python中的多维数组_dtype_09

python构造多维数组 python中的多维数组_dtype_10

记不住NumPy的dtype也没关系。通常只需要知道你所处理的数据大致类型是浮点数、整数、复数、布尔值、字符串还是普通的Python对象即可。当你需要控制数据在内存和磁盘中存储方式时(尤其是大数据集),那就得了解如何控制存储类型。

  • astype函数

数组的astype函数可以明确的把一个数组从一个dtype转换成另一个dtype:

#整数数组 转换 浮点数数组
arr = np.array([1,2,3,4,5])  #如果元素全为整数  默认数据类型 int64
print(arr.dtype)

float_arr = arr.astype(np.float64)
print(float_arr.dtype)
print("--------------------------")
#浮点数数组 转换 整数数组
arr1 = np.array([1,2.5,3.5,4.5,5.5])  #如果有元素是浮点数  默认数据类型 float64
print(arr1.dtype)
int_arr = arr1.astype('int32') 
print(int_arr.dtype)

python构造多维数组 python中的多维数组_Python数组_11

如果一个字符串数组全是数字,可以使用astype把它转换为数值形式:

str1 = np.array(['1.2','2.45','3.88'],dtype=np.string_)
print(str1.astype(float))
#print(str1.astype(np.float64))

python构造多维数组 python中的多维数组_python构造多维数组_12

使用np.string_类型时,一定注意,因为NumPy的字符串数据大小固定,发生截取时,不会发出警告。pandas提供了更多非数值数据的便利的处理方法。

如果转换过程中因为某种原因失败了(比如某个不能被转换为float64的字符串),就会引发一个ValueError。我们之前写的是float而不是np.float64,NumPy很聪明,它会将Python类型映射到等价的dtype上。

int_array = np.arange(10)
flo_array = np.array([0.22,.27,9.88],dtype=np.float64)
print(int_array.astype(flo_array.dtype))
print(int_array)

python构造多维数组 python中的多维数组_python构造多维数组_13

调用astype总会创建一个新的数组(一个数据备份),即使新的dtype和旧的dtype相同。

 

还可以使用简洁的类型代码来表示dtype:

empty_uint32 = np.empty(8,dtype='u4')   #'uint32'  np.uint32
empty_uint32

python构造多维数组 python中的多维数组_Python数据分析_14

4.ndarray对象的内部机理

NumPy的ndarray提供了一种将同质数据块(可以是连续或跨越)解释为多维数组对象的方式。正如之前看到的一样,数据类型(dtype)决定了数据的解释方式,比如浮点数、整数、布尔值等。

ndarray如此强大的原因是所有数组对象都是数据块的一个跨度视图。你可能想知道数组视图arr[::2,::-1]不复制任何数据的原因是什么。简单来说,ndarray不只是一块内存和一个dtype,他还有跨度信息,这使得数组能以各种步幅在内存中移动。更准确来讲,ndarray内部由以下内容组成:

python构造多维数组 python中的多维数组_dtype_15

例如一个10*5的数组,其形状为(10,5):

python构造多维数组 python中的多维数组_Python数据分析_16

一个典型的(C顺序,以后会讲)3*4*5的float64(8个字节)数组,其跨度为(160,40,8),知道跨度非常有用,通常跨度在一个轴上越大,沿这个轴进行计算的开销就越大:

python构造多维数组 python中的多维数组_Python数组_17

虽然NumPy用户很少会对数组的跨度信息感兴趣,但他们却是构建非复制式数组视图的重要因素。跨度甚至可以是负数,这样会使数组在内存中后向移动,比如在切片obj[::-1]或obj[:,::-1]中就是这样。

5.NumPy数据类型体系

可能偶尔需要检查数组中所包含的是否是整数、浮点数、字符串或Python对象。因为浮点数的种类很多(float16到float128),判断dtype是否属于某个大类的工作非常繁琐。还好,dtype都有一个超类(如np.integer和np.floating),他们可以跟np.issubdtype函数结合使用:

ints = np.ones(10,dtype=np.uint32)
floats = np.ones(10,dtype=np.float32)
print(np.issubdtype(ints.dtype,np.integer))
print(np.issubdtype(floats.dtype,np.floating))
print(np.float64.mro())   #查看np.float64的所有父类
print(np.issubdtype(ints.dtype,np.number))

python构造多维数组 python中的多维数组_ndarray_18

大部分NumPy用户不需要完全了解这些知识,但是这些知识偶尔会派上用场,下图说明了dtype体系以及父子类关系:

python构造多维数组 python中的多维数组_ndarray_19