数据分析:
数据准备(读写各种各样的文件格式和数据库)
数据处理(对数据进行清洗、修整、整合等处理以便进行分析)
数据分析(根据分析目的对数据集做合适的数学和统计运算)
数据可视化(展示数据分析成果)
一.NumPy简介
1.
(1.NumPy(Numerical Python的简称)是高性能科学计算和数据分析的基础包,提供以下功能
ndarray,一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组
用于对整组数据进行快速运算的标准函数(无需编写循环)
用于读写磁盘数据的工具以及用于操作内存映射文件的工具
线性代数、随机数生成以及傅里叶变换功能
用于集成由C、C++、Fortran等语言编写的代码的功能
(2.NumPy的安装
a.首先请确定你的Python是32bit还是64bit,方法如下:
顺序选取Windows的开始菜单“所有程序” “Python3.8” IDLE(Python 3.8 64bit) 或者IDLE(Python 3.8 32bit)
或者使用如下语句测试:
>>> import platform
>>> platform.architecture()
(‘32bit', 'WindowsPE')
如果是32bit,请到http://www.lfd.uci.edu/~gohlke/pythonlibs/下载文件numpy-1.18.5+mkl-cp38-cp38-win32.whl
如果是64bit, 则到同一网站下载文件 numpy‑1.18.5+mkl‑cp38‑cp38‑win_amd64.whl
b.将.whl文件存放在Python的Scripts目录中,在DOS命令行中将当前目录转换为Python目录下的Scripts子目录(使用cd命令,表示change directory),然后使用pip安装NumPy,具体如下(以Python 32bit为例):
如果此时numpy-1.18.5+mkl-cp38-cp38-win32.whl不在当前的目录下,则必须给出其绝对路径
2.NumPy的数据结构--ndarray
(1.ndarray是一种N维数组对象,其中所有的元素必须是相同类型的
>>> import numpy as np #随后代码示例皆默认已导入numpy库 >>> data1=[[1,2,3,4],[5,6,7,8]] >>> arr1=np.array(data1) >>> arr1 array([[1, 2, 3, 4], [5, 6, 7, 8]]) >>> arr1.shape # 返回一个表示各维度大小的元组 (2, 4) >>> arr1.dtype #返回一个用于说明数组数据类型的对象 dtype('int32')
(2.创建ndarray
a. 除np.array之外,还有一些函数也可以用于新建数组,例如zeros和ones可以创建指定长度或形状的全0或全1数组,而empty可以创建一个没有任何具体值的数组
>>> import numpy as np >>> np.zeros((3,6)) array([[0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0.], [0., 0., 0., 0., 0., 0.]]) >>> np.empty((2,3)) array([[9.34611827e-307, 9.34601641e-307, 1.95818994e-306], [6.23036978e-307, 6.23040373e-307, 8.90104239e-307]])
很多情况下,np.empty返回的都是一些未初始化的值
b.arange是Python内置函数range的数组版
>>> np.arange(15) array([ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]) >>> np.arange(2, 15, 2) # 设置起始和终止索引及步长 array([ 2, 4, 6, 8, 10, 12, 14])
(3.ndarray的数据类型
a.dtype(数据类型)是一个特殊的对象,它含有将一块内存解释为特定数据类型所需的信息:
>>> arr1 = np.array([1, 2, 3], dtype = np.float64) >>> arr2 = np.array([1, 2, 3], dtype = np.int32) >>> arr1.dtype dtype('float64') >>> arr2.dtype dtype('int32’)
dtype是Python如此强大和灵活的原因之一,
多数情况下它们直接映射到相应的机器表示,
这使得“读写磁盘上的二进制数据流”以及“集成低级语言代码(如C和Fortran)”等工作变得更加简单
b.
可以通过ndarray的astype方法显式地转换其dtype >>> arr = np.array([1, 2, 3, 4, 5]) >>> arr.dtype dtype('int32') >>> float_arr = arr.astype(np.float64) # 整数转换为浮点数 >>> float_arr.dtype dtype('float64’) 数组的dtype的另外一个用法 >>> int_array = np.arange(10) >>> calibers = np.array([.22, .270, .357, .380, .44, .50], dtype = np.float64) >>> int_array.astype(calibers.dtype) array([0., 1., 2., 3., 4., 5., 6., 7., 8., 9.])
(4.数组和标量之间的运算
数组很重要,因为它使你可以不用编写循环即可对数据执行批量运算,大小相等的数组之间的任何算数运算都会将运算应用到元素级
>>> arr = np.array([[1,2,3],[4,5,6]]) # 创建数组使用array函数 >>> arr*arr array([[ 1, 4, 9], [16, 25, 36]]) >>> arr-arr array([[0, 0, 0], [0, 0, 0]]) >>> 1/arr # 数组和标量之间的运算会将标量值传播到各元素 array([[ 1. , 0.5 , 0.33333333], [ 0.25 , 0.2 , 0.16666667]])
(5.基本的索引和切片
a.NumPy数组的索引是一个内容丰富的主题,因为选取数据子集或单个元素的方式有很多。一维数组很简单,从表面上看和Python列表的功能类似
>>> arr = np.arange(10) >>> arr array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> arr[5] 5 >>> arr[5:8] array([5, 6, 7]) >>> arr[5:8] = 12 #将标量值赋值给一个切片,该值自动传播 >>> arr array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9])
b.与列表最重要的区别在于,数组切片是原始数组的视图。这就意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上
>>> arr array([ 0, 1, 2, 3, 4, 12, 12, 12, 8, 9]) >>> arr_slice = arr[5:8] >>> arr_slice[1] = 12345 >>> arr array([ 0, 1, 2, 3, 4, 12, 12345, 12, 8, 9]) >>> arr_slice[:] = 64 >>> arr_slice array([64, 64, 64]) >>> arr array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9])
c.因为NumPy的设计目的是处理大数据,假如NumPy要将数据到处复制会产生性能和内存方面的问题
如果想要得到ndarray切片的一份副本而不是视图,就需要显示地进行复制操作,例如
>>> arr array([ 0, 1, 2, 3, 4, 64, 64, 64, 8, 9]) >>> arr_copy = arr[5:8].copy() # 得到ndarray切片的副本 >>> arr[5:8] = 128 >>> arr array([ 0, 1, 2, 3, 4, 128, 128, 128, 8, 9]) >>> arr_copy array([64, 64, 64])
(6.切片索引
ndarray的切片语法跟Python列表这样的一维对象的切片语法类似
>>> arr[1:6] array([ 1, 2, 3, 4, 128]) 高维度对象上支持的操作更多 >>> arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> arr2d array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) >>> arr2d[:2] # 选取前两行的所有元素构成的数组 array([[1, 2, 3], [4, 5, 6]]) >>> arr2d[:2, 1:] # 选取前两行和后两列中重复元素组成的数组 array([[2, 3], [5, 6]]) >>> arr2d[2, :] # 选取最后一行的所有元素组成的数组 array([7, 8, 9])
3.NumPy-布尔索引
(1.布尔索引
>>> names = np.array(['Bob','Joe','Will','Bob','Joe’]) >>> data = np.random.randn(5,4) #生成正态分布的随机数据 >>> data array([[ 0.06577781, -0.33904047, 0.32801625, -0.4534386 ], [-0.57919606, -1.19820161, 0.16266142, 0.29625658], [-0.78579447, 0.14912636, 1.03945375, -0.23016623], [-2.71780916, -0.48087538, -0.3988084 , -0.3054676 ], [-0.91710932, -0.47175947, -2.19321508, -0.53418279]]) 假设每个名字都对应data数组中的一行,而我们想要选出对应于名字“Bob”的所有行
跟算术运算一样,数组的比较运算(如==)也是矢量化(使用数组表达式代替循环的做法称为矢量化)的
>>> names == ‘Bob’ #对names和‘Bob’比较运算将会产生一个布 # 尔型数组 array([ True, False, False, True, False], dtype=bool) >>> data[names == 'Bob'] #布尔型数组可用于数组索引 array([[ 0.06577781, -0.33904047, 0.32801625, -0.4534386 ], [-2.71780916, -0.48087538, -0.3988084 , -0.3054676 ]])
布尔型数组的长度必须和被索引的轴长度一致(此处为5)
通过布尔索引选取数组中的数据将总是创建数据的副本
(2.花式索引:式索引(Fancy indexing)是一个NumPy术语,它指的是利用整数数组进行索引
>>> arr = np.empty((5,4)) #创建一个5*4的没有任何具体(有意义的)值的数组 >>> for i in range(5): arr[i] = i >>> arr array([[ 0., 0., 0., 0.], [ 1., 1., 1., 1.], [ 2., 2., 2., 2.], [ 3., 3., 3., 3.], [ 4., 4., 4., 4.]]) 为了以特定顺序选取子集,只需传入指定顺序的整数列表或ndarray即可: >>> arr = np.empty((5,4)) >>> for i in range(5): arr[i] = i >>> arr array([[0., 0., 0., 0.], [1., 1., 1., 1.], [2., 2., 2., 2.], [3., 3., 3., 3.], [4., 4., 4., 4.]]) >>> arr[[3, 0, 1]] array([[3., 3., 3., 3.], [0., 0., 0., 0.], [1., 1., 1., 1.]])
使用负数索引将会从末尾开始选取行
需要注意的是,花式索引总是将数据复制到新的数组中,源数组保持不变
4.通用 函数
通用函数(即ufunc)是一种对ndarray中的数据执行元素级运算的函数
>>> arr = np.arange(10) >>> arr array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) >>> np.sqrt(arr) array([ 0., 1., 1.41421356, 1.73205081, 2., 2.23606798, 2.44948974, 2.64575131, 2.82842712, 3. ]) 其中sqrt是一元(unary)ufunc
另外一些(如add或maximum)接受两个数组(因此也叫二元(binary)ufunc),并返回一个结果数组: >>> x = np.random.randn(8) #生成一个包含8个随机浮点数 的一维数组 >>> y = np.random.randn(8) >>> x array([1.37810951, 0.84643835, 0.91996356, 0.20437262, 1.460486, 0.21984669, 1.72858396, 0.53766818]) >>> y array([-1.46021875, -0.28856923, -2.42218969, 1.86268091, -0.64028001, 1.63904199, -2.81964605, -0.34841254]) >>> np.maximum(x,y) #求两个数组中对应位置上最大值 array([1.37810951, 0.84643835, 0.91996356, 1.86268091, 1.460486, 1.63904199, 1.72858396, 0.53766818])
5.利用数组进行数据处理
(1.NumPy数组将许多数据处理任务表述为简洁的数组表达式,使用数组表达式代替循环的做法,通常称为矢量化。矢量化数组运算通常要比等价的纯Python方式快上一两个数量级(甚至更多)
假设我们要在一组值(网格型)上计算函数
。np.meshgrid函数接受两个一维数组,并产生两个二维矩阵(对应于两个数组中所有的(x,y)对)
>>> points = np.arange(-5,5,0.01) #从-5到5按步长0.01产生一个包含1000个元素的一维数组 >>> xs,ys = np.meshgrid(points,points) #xs、ys分别存储# 了(x,y)对在x轴和y轴上的坐标 # 从坐标向量(points)返回坐标矩阵(xs和ys) >>> xs array([[-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99], [-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99], ..., [-5. , -4.99, -4.98, ..., 4.97, 4.98, 4.99]]) ** 上面xs中, points变成了矩阵的行向量,重复1000次 >>> ys array([[-5. , -5, -5, ..., -5, -5, -5], [-4.99 , -4.99, -4.99, ..., -4.99, -4.99, -4.99], [-4.98 , -4.98, -4.98, ..., -4.98, -4.98, -4.98], ..., [4.99, 4.99, 4.99, ..., 4.99, 4.99, 4.99]]) ** 上面ys中, points变成了矩阵的列向量, 重复1000次 >>> import matplotlib.pyplot as plt >>> plt.imshow(z, cmap = plt.cm.gray) >>> plt.colorbar() >>> plt.show()
二.pandas简介
pandas提供了使我们能够快速便捷地处理结构化数据的数据结构和函数,其兼具NumPy高性能的数组计算功能以及电子表格和关系型数据库(如SQL)灵活的数据处理功能
它提供了复杂精细的索引功能,以便更为便捷地完成重塑、切片和切块、聚合以及选取数据子集等操作
-----安装pandas
pandas与前面介绍的NumPy的下载与安装的方式类似:到http://www.lfd.uci.edu/~gohlke/pythonlibs/下载文件
pandas‑1.0.4‑cp38‑cp38‑win32.whl或者pandas‑1.0.4‑cp38‑cp38‑win_amd64.whl
然后在DOS命令行中将当前目录转换为Python目录下的Scripts子目录,然后使用pip安装pandas,具体如下(以Python 32bit为例):
1.pandas的数据结构--DataFrame
(1. DataFrame是一个表格型的数据结构,它含有一组有序的列,每列可以是不同的值类型
(2.DataFrame既有行索引也有列索引
(3.构建DataFrame的办法有很多,最常用的一种是直接传入一个由等长列表组成的字典
>>> import pandas as pd #随后代码示例皆默认已导入pandas库 >>> data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada'], 'year': [2000, 2001, 2002, 2001, 2002], 'pop': [1.5, 1.7, 3.6, 2.4, 2.9]} >>> frame1 = pd.DataFrame(data) >>> frame1 pop state year 0 1.5 Ohio 2000 1 1.7 Ohio 2001 2 3.6 Ohio 2002 3 2.4 Nevada 2001 4 2.9 Nevada 2002 如果指定了列序列,则DataFrame的列就会按照指定顺序进行排列: >>> frame2=pd.DataFrame(data, columns=['year', 'state', 'pop'], index=['one','two','three','four','five']) #columns指定了列索引的排列位置 #index指定了行索引的名称 >>> frame2 year state pop one 2000 Ohio 1.5 two 2001 Ohio 1.7 three 2002 Ohio 3.6 four 2001 Nevada 2.4 five 2002 Nevada 2.9
2.重新索引