Numpy 简介
import numpy as np
Numpy是应用Python进行科学计算的基础库。它的功能包括多维数组、基本线性代数、基本统计计算、随机模拟等。Numpy的核心功能是ndarray 类,即多维数组。多维数组是线性代数中非常广泛的概念,如一维数组就是向量,二维数组是矩阵。在数组中,要求所有元素必须是同一类型,这是与列表与字典的区别之一一。针对数组,通过Numpy可以实现的基本操作包括数组的创建、数组切片、数组重组、数组运算等。01
数组的创建
常见的创建数组的方法之一:转换Python的列表、元组等数据结构为数组类型。下面实例给出了创建数组的常用命令。>>> import numpy as np # 载入Numpy库简写为"np">>> arr1 = np.array([1,2,3,4,5,6])>>> arr1array([1, 2, 3, 4, 5, 6])>>> type(arr1) # 查看数据类型numpy.ndarray>>> arr1.shape # 各个维度的数组长度(6,)>>> arr2 = np.array([[1,2,3],[4,5,6]])>>> arr2 array([[1, 2, 3], [4, 5, 6]])>>> arr2.shape(2, 3)
另外,还可以利用Numpy的内置函数来直接创建数组。>>> arr3 = np.arange(0,1,0.1)>>> arr3array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])# 创建一维长度为2,二维长度为3的元素全为0的数组>>> arr4 = np.zeros((2,3)) >>> arr4 array([[ 0., 0., 0.], [ 0., 0., 0.]])# 创建一维长度为2,二维长度为3的元素全为1的二维数组>>> arr5 = np.ones((2,3)) >>> arr5array([[ 1., 1., 1.], [ 1., 1., 1.]])# 创建一维长度为2,二维长度为3的二维空数组>>> arr6 = np.empty([2,3]) >>> arr6array([[ 1., 1., 1.], [ 1., 1., 1.]]) # 从[0,1]区间的均匀分布随机抽取四个数>>> arr7 = np.random.rand(4)>>> arr7array([ 0.36570416, 0.83097711, 0.98761922, 0.87057992])# 生成一个标准正态分布的4*4样本值>>> arr8 = np.random.normal(size=(4,4)) >>> arr8array([[-0.15990639, 0.7088309 , -0.20267733, 2.14992874], [ 0.05542048, -1.15103197, 0.21129526, 0.6212253 ], [-1.31547565, 1.4401065 , 0.6680733 , -0.60608497], [-1.03471769, 0.55338916, -0.05869825, 0.61610795]])
注意这里的 np.arange() 可以指定步长为(0,1)为小数,而Python内置函数range无此功能。另外,np.random 中包括多种概率分布的随机样本,是数据分析辅助的重点工具之一。02
数组的切片与索引
数组的截取与 list 相同,可以通过 [] 来指定每个维度的索引。>>> import numpy as np>>> a = np.array([[1,2,3,4,5],[6,7,8,9,10]])>>> print(a)[[ 1 2 3 4 5] [ 6 7 8 9 10]]>>> print(a[0:1]) # 截取第一行[[1 2 3 4 5]]>>> print(a[1,2:5]) # 截取第二行,第三、四、五列[ 8 9 10]>>> print(a[1:]) # 截取第二行[[ 6 7 8 9 10]]
另外,在应用中经常需要返回满足给定条件的数组元素。为此,下面介绍一个按照条件索引的数组操作。>>> b = a[a>6] # 截取矩阵中大于6的元素,范围是一维数组>>> print(b)[ 7 8 9 10]
03
数组重组
数组重组主要是指对原来数组进行修改,具体包括数组类型修改、数组维度修改与数组元素修改。>>> # 数组元素的数据类型为字符串>>> num_str1 = np.array(['1.2','2.4','3.6'],dtype=np.string_)>>> # 利用astype转换为浮点型>>> num_str1.astype(float)array([ 1.2, 2.4, 3.6])>>> data = np.arange(6)>>> # 利用reshape 指定新数组各个维度>>> data = data.reshape(2,3) >>> dataarray([[0, 1, 2], [3, 4, 5]])>>> # data中小于3的元素用0代替,否则用1代替>>> np.where(data < 3,0,1) array([[0, 0, 0], [1, 1, 1]])
这里 np.where(condition,x,y)函数是三元表达式:满足条件(condition),输出 x ,不满足输出 y 。04
数组运算
数学中的加减乘除运算同样也使用于数组。在数组中是按照元素级进行批量运算的,下面挑选几个实例来说明这一点:>>> arr7 = np.array([[1,2,3],[4,5,6]])>>> arr7array([[1, 2, 3], [4, 5, 6]])>>> arr7 * 2 # 数组的每个每个元素都乘以2array([[ 2, 4, 6], [ 8, 10, 12]])>>> arr7*arr7 # 两个数组对应的元素进行运算array([[ 1, 4, 9], [16, 25, 36]])>>> np.log(arr7) # 数组的每个元素都取 logarray([[ 0. , 0.69314718, 1.09861229], [ 1.38629436, 1.60943791, 1.79175947]])
除了上述简单的元素级运算,数组也可以进行各种矩阵运算,如矩阵向量的混合运算、矩阵求逆、矩阵行列式、矩阵特征值。>>> A = np.array([[0,1],[2,3]])>>> Aarray([[0, 1], [2, 3]])>>> v = np.array([1,2])>>> varray([1, 2])>>> v.dot(A) # dot是内积运算,运算规则与线性代数相同array([4, 7])>>> A.dot(v) # 这里v看作列变量array([2, 8])
Numpy 库为Python中的数组运算提供了很多便捷,这里只列举了常用的少数几个操作命令。其实,Numpy可以看作计算科学的基础模块,而接下来介绍的pandas库是在Numpy基础上的拓展,也具备Numpy中的许多功能,而且不要求数据类型必须单一。pandas 简介
import pandas as pd
Pamdas是建立在 Numpy库之上的,是使得数据分析工作变得更简单更快的高级操作工具。pandas的进行数据处理主要针对两种数据结构:Series 和 DataFrame 。Series
Series 是建立在 pandas 库之上的,是使得数据分析工作变得更简单更快的高级操作工具。引入索引的一大作用是数据对其功能,使得进行数据处理后不会发生数据错行。最简单的 Series 可以由一个列表类型的数据生成:>>> import pandas as pd>>> ser1 = pd.Series([1,3,5,7])>>> ser10 11 32 53 7dtype: int64
Series的数据变现形式:索引在左侧,值在右边,默认的索引是从0开始的整数型序列。我们也可以在创建的时候通过 index 参数指定索引数据。>>> ser2 = pd.Series([1,3,5,7], index=['a','b','c','d'])>>> ser2a 1b 3c 5d 7dtype: int64
在创建 Series 后可以对它们的一些属性进行修改,如下所示:>>> ser2.indexIndex(['a', 'b', 'c', 'd'], dtype='object')>>> ser2.index = ['A','B','C','D']>>> ser2A 1B 3C 5D 7dtype: int64
对 Series 中特定数据的查找,可以通过以下几种方式来实现:>>> ser2['A'] # 通过索引值查找值1>>> ser2[1] # 通过行号查找值3>>> ser2[0:2] # 通过切片来查找子序列A 1B 3dtype: int64
在 Series 类型运算中,输出结果会自动对齐不同索引的数据。当序列中没有共同的索引时,则输出缺失值符号 NaN :>>> ser3 = pd.Series([1,3,5],index=['a','b','c'])>>> ser4 = pd.Series([2,4,6],index=['c','d','b'])>>> ser3 + ser4a NaNb 9.0c 7.0d NaNdtype: float64
上述这种运算机制在数据处理中非常有用,按照索引来进行运算可以避免错误分行。总结:Series 基本操作类似数组和字典,它们之间可以相互转换。但是,序列是顺序指定的、具有索引的数据类型。数组是没有索引的,而字典的元素是无序的。Dataframe
DataFrame是将若干个 Series 按列合并而成的二维数据结构,每一列单独取出来就是一个 Series 。数据框 DataFrame是用于存储多行和多列的数据集合,是机器学习算法读取数据的最常用格式。就像日常见到的二维 Excel 表格一样,第一行默认表示变量名,后续每行为一个样本,而每列表示变量(特征)的取值。利用数据框之前需要导入处理数据的核心库 pandas 。下列几行代码基本包括了 DataFrame 的创建。>>> import pandas as pd # 导入 Python 库 pandas>>> dic1 = {"age":[18,20,22],"name":["xiaoming","wanghan","hanwei"],"Chinese":[90,78,97],"Math":[87,69,89],"English":[98,78,83],"History":[86,79,80],"Physics":[99,78,94]}>>> df = pd.DataFrame(dic1,index=['a','b','c'])>>> print(df) age name Chinese Math English History Physicsa 18 xiaoming 90 87 98 86 99b 20 wanghan 78 69 78 79 78c 22 hanwei 97 89 83 80 94
从上面实例可以看出,数据框是由字典 data 直接转化而来。实际数据分析中,采集到的数据结构往往是多种类型的,而数据框恰好可以存放不同类型的数据。另外,利用 Python 读取的数据往往自动转化为数据框类型的,如前面介绍的读取本地数据命令 pd.read_csv() 。01
了解数据全貌
一旦把数据载入到 Python 中,首先要做的是了解数据的全貌与基本特征。例如,要知道数据框大小(行和列)、列变量名、索引号、数据类型等。如果想知道数据框的列变量与索引名称,可以使用如下命令>>> print(df.columns) # 列变量名称Index(['age', 'name', 'Chinese', 'Math', 'English', 'History', 'Physics'], dtype='object')>>> print(df.index) # 索引序列Index(['a', 'b', 'c'], dtype='object')>>> print(df.shape) # 行数与列数(3, 7)
另外,Python 中存在一些内置函数可以输出许多数据框属性,例如:>>> df.info() # 整体汇总<class 'pandas.core.frame.DataFrame'>Index: 3 entries, a to cData columns (total 7 columns):age 3 non-null int64name 3 non-null objectChinese 3 non-null int64Math 3 non-null int64English 3 non-null int64History 3 non-null int64Physics 3 non-null int64dtypes: int64(6), object(1)memory usage: 168.0+ bytes>>> df.describe() # 对每一列数值型数据进行统计,包括计数、均值、标准差、标准差、各个分位数等 age Chinese ... History Physicscount 3.0 3.000000 ... 3.000000 3.000000mean 20.0 88.333333 ... 81.666667 90.333333std 2.0 9.609024 ... 3.785939 10.969655min 18.0 78.000000 ... 79.000000 78.00000025% 19.0 84.000000 ... 79.500000 86.00000050% 20.0 90.000000 ... 80.000000 94.00000075% 21.0 93.500000 ... 83.000000 96.500000max 22.0 97.000000 ... 86.000000 99.000000[8 rows x 6 columns]>>> df.describe(include=["object"]) # 基本统计描述(指定变量为类别型) namecount 3unique 3top wanghanfreq 1
02
访问数据
访问数据框一列与若干列的常用的方法有如下两种:>>> df["name"] # 按列变量访问a xiaomingb wanghanc hanweiName: name, dtype: object>>> df.iloc[:,3] # 按照列数访问,这里表示第二列对应的所有行a 87b 69c 89Name: Math, dtype: int64>>> df[["name","age","Math"]] # 指定列变量名 name age Matha xiaoming 18 87b wanghan 20 69c hanwei 22 89>>> df.iloc[:,:3] # 按照列数访问,这里表示前两列对应所有行 age name Chinesea 18 xiaoming 90b 20 wanghan 78c 22 hanwei 97>>> df.head() # 默认输出前五行 age name Chinese Math English History Physicsa 18 xiaoming 90 87 98 86 99b 20 wanghan 78 69 78 79 78c 22 hanwei 97 89 83 80 94>>> df.tail() # 默认输出后五行 age name Chinese Math English History Physicsa 18 xiaoming 90 87 98 86 99b 20 wanghan 78 69 78 79 78c 22 hanwei 97 89 83 80 94
类似的,访问数据框的行有如下几种方法:>>> df[1:2] # 取第二行 age name Chinese Math English History Physicsb 20 wanghan 78 69 78 79 78>>> df.iloc[1,:] # 按照行数访问,这里表示第二行对应的所有列age 20name wanghanChinese 78Math 69English 78History 79Physics 78Name: b, dtype: object>>> df.iloc[0:2,] # 前两行的所有列 age name Chinese Math English History Physicsa 18 xiaoming 90 87 98 86 99b 20 wanghan 78 69 78 79 78>>> df.iloc[1,1] # 第二行第二列'wanghan'
03
数字特征统计
既然数据框是个数据集合,那么我们经常需要对其进行一些基本统计描述。下面几行代码给出了常用的统计描述的操作:>>> print(df.mean()) # 默认对数值型的所有列分布求平均age 20.000000Chinese 88.333333Math 81.666667English 86.333333History 81.666667Physics 90.333333dtype: float64>>> df.sum() # 列求和,方式类似 meanage 60name xiaomingwanghanhanweiChinese 265Math 245English 259History 245Physics 271dtype: object>>> df.max() # 求最大值,求最小值用 df.min()age 22name xiaomingChinese 97Math 89English 98History 86Physics 99dtype: object>>> df.isnull() # 布尔值输出,检查每列是否有缺失值 age name Chinese Math English History Physicsa False False False False False False Falseb False False False False False False Falsec False False False False False False False>>> df['age'].unique() # 该列不同值的个数array([18, 20, 22], dtype=int64)>>> df['age'].value_counts() # 统计某一列 'age' 中各个值出现的次数18 122 120 1Name: age, dtype: int64