python学习笔记(2):科学计算及数据可视化入门
一、NumPy
1.NumPy:Numberical Python
2.高性能科学计算和数据分析的基础包
3.ndarray,多维数组(矩阵),具有矢量运算的能力,快速、节省空间
(1)ndarray,N维数组对象(矩阵)
(2)所有元素必须是相同类型
(3)ndim属性,维度个数
(4)shape属性,各维度的大小
(5)dtype属性,数据类型
4.矩阵运算,无需循环,可完成类似Matlab中的矢量计算
5.线性代数、随机数生成
6.import numpy as np
narray多维数组 import numpy as np #生成指定维度的随机多维数组 data = np.random.rand(2,3) //生成一个两行三列的多维数组 print data
print type(data) //查看数据类型,这个地方数据类型是numpy.ndarray的数据类型
[[0.16088508 0.86321185 0.25653982] [0.42456419 0.33277194 0.30046417]] <class 'numpy.ndarray'>
#
print '维度个数', data.ndim //维度个数 2 维度个数有两个,第0个维度大小是2,第一个维度大小是3
print '各维度的大小', data.shape //各维度的大小:(2L,3L) L代表的是Long
print '数据类型:',data.dtype //float 64 数据类型是float64位的数据
创建ndarray
np.array(collection),collection为序列性对象(list),嵌套序列(list of list),嵌套的数据结构为:[[],[],[]]
#嵌套序列转换为ndarray
l2=[range(10),range(10)]
data=np.array(l2)
print(data)
print(data.shape)
[[0 1 2 3 4 5 6 7 8 9] [0 1 2 3 4 5 6 7 8 9]] //创建一个两行10列的数组 (2, 10) //第一个维度的大小是2,第二个维度的大小是10
#np.zeros , np.ones和np.empty
#np.zeros 创建一个全零的数组
zeros_arr = np.zeros((3,4))
#如果创建np.zeros(3,4),那么计算机就认为3是第一个参数,4是第2个参数
#np.ones创建一个全为1的数组
ones_arr=np.ones((2,3))
#np.empty,创建一个3行3列为空的数组
empty_arr=np.empty((3,3))
#np.empty指定数据类型
empty_int_arr = np.empty((3,3),int)
7.创建ndarray(续)
np.arange()类似range(),是arange,不是英文arrange
#np. arange() print np.arange(10) [0,1,2,3,4,5,6,7,8,9] //创建0-9这样的一个一维数组
8.ndarray数据类型
dtype,数据类型+位数,如float64表示float类型64位的;int32表示int类型32位的
9.数据类型转换:astype
#创建一个全0的3行4列的float型的数组 zeros_float_arr= np.zeros((3,4),dtype=np.float64) print(zeros_float_arr)#创建一个3行4列的数组 print(zeros_float_arr.dtype)#打印出数组的数据类型
[[0. 0. 0. 0.] [0. 0. 0. 0.] [0. 0. 0. 0.]] float64
#astype转换数据类型
zeros_int_arr=zeros_float_arr.astype(np.int32)#将数组转换为int型32位的数据类型
print(zeros_int_arr)#打印出全0的数组
print(zeros_int_arr.dtype)#打印出数据类型
[[0 0 0 0] [0 0 0 0] [0 0 0 0]] int32
8.矢量化(vectorization)
矢量运算,相同大小的数组键间的运算应用在元素上
矢量和标量的运算,"广播"---》将标量"广播"到各个元素
#矢量与矢量的运算,这个地方要注意矩阵的输入和输出之间的区别 arr = np.array([[1,2,3],[4,5,6]]) print("矩阵相乘:",(arr*arr)) print("矩阵相加:",(arr+arr))
9.索引和切片
一维数组的索引与python的列表索引功能类似
多维数组的索引,list[0,1,2,3,4,5,,6,7,8,9]可以通过[:]的方式将列表中的所有元素都取出来;[1:4]就可以将[1,2,3]这几个元素切割出来,第二个元素是不包括在里面的,第一个元素是包括在里面的,也就是左闭右开的区间;[1:]表示从1开始直到取到最后一个元素;[:4]表示从起始位置到第四个元素,而且是不包含第四个元素的
(1)多维数组的索引
arr[r1:r2,c1:c2]
arr[1,1]等价于arr[1][1]
:表示某个维度的数据
#一维数组 arr1 = np.arange(10) print(arr1) print(arr1[2:5])
[0 1 2 3 4 5 6 7 8 9] [2 3 4]
#多维数组
arr2=np.arange(12).reshape(3,4) #这里讲0-11这12个元素进行重新设置为3行4列的数组
print(arr2)#创建一个3行4列的数组,打印出arr2这个数组
print(arr2[1])#打印出第2行的所有元素
print(arr2[0:2,2:])
print(arr2[:,1:3])#输出3行,并输出第一列和第二列的数据
(2)条件索引:布尔值多维数组 arr[condition] condition可以是多个条件的组合。注意,多个条件的组合要使用& | ,而不是and or
#条件索引 #找出data_arr中2005年以后的数据 data_arr=np.random.rand(3,3)#生成一个3x3的随机数组 print(data_arr)
[[0.68836436 0.53529652 0.50301061] [0.13000854 0.3235649 0.81903217] [0.53004262 0.64210184 0.07219503]]
year_arr=np.array([[2000,2001,2000],[2005,2002,2009],[2001,2003,2010]])#创建一个年份的数组 is_year_after_2005=year_arr>=2005#判断每个年份是否大于2005年 print(is_year_after_2005,is_year_after_2005.dtype)#打印数据以及类型
[[False False False] [ True False True] [False False True]] bool
#多个条件
filtered_arr = data_arr[(year_arr<=2005)&(year_arr%2)==0]
print(filtered_arr)
(3)维度转换
转置transpose,高维数组转置需要指定维度编号(0,1,2,3...........)
#转置 arr = np.random.rand(2,3)#生成2行3列的矩阵 print(arr) print(arr.transpose())#将矩阵进行转置操作,就是讲2行3列的矩阵转换成3行2列的矩阵
[[0.08678526 0.31923682 0.20847803] [0.69693766 0.03117802 0.06704059]] [[0.08678526 0.69693766] [0.31923682 0.03117802] [0.20847803 0.06704059]]
#生成一个3维的随机矩阵 arr3d=np.random.rand(2,3,4)#生成2行3列纵向是4个维度的矩阵,第0个维度的大小是2,第一个维度里的有3个元素,再往里走,每个维度上有4个数据 print(arr3d) print('..............................') print(arr3d.transpose(1,0,2))#3x2x4
[[[0.88454675 0.0208522 0.81164518 0.01420287] [0.47094116 0.39709142 0.25520182 0.38764961] [0.08688397 0.76869897 0.84866046 0.67766179]] [[0.93766484 0.01070791 0.71081915 0.8134657 ] [0.77591357 0.88554432 0.49956425 0.1281943 ] [0.29816972 0.36204365 0.34020235 0.50780135]]] .............................. [[[0.88454675 0.0208522 0.81164518 0.01420287] [0.93766484 0.01070791 0.71081915 0.8134657 ]] [[0.47094116 0.39709142 0.25520182 0.38764961] [0.77591357 0.88554432 0.49956425 0.1281943 ]] [[0.08688397 0.76869897 0.84866046 0.67766179] [0.29816972 0.36204365 0.34020235 0.50780135]]]
10.通用函数(ufunc):元素级别的运算
常用的通常函数
ceil 向上最接近的整数
floor 向下最接近的整数
rint 四舍五入
isnan 判断元素是否为NaN(Not a Number)
multiply 元素相乘
divide 元素相除
arr = np.random.randn(2,3)#生成一个2行3列的随机数组 print(arr) print(np.ceil(arr))#生成向上最接近的整数 print(np.floor(arr))#生成向下最接近的整数 print(np.rint(arr))#生成四舍五入的整数 print(np.isnan(arr))#判断元素是否为nan(Not a Number)
[[1.17185068 0.37997147 2.40529222] [2.26526699 0.10131456 1.48745395]] [[2. 1. 3.] [3. 1. 2.]] [[1. 0. 2.] [2. 0. 1.]] [[1. 0. 2.] [2. 0. 1.]] [[False False False] [False False False]]
11.np.where
矢量版本的三元表达式x if condition else y
np.where(condition,x,y) //这个地方,如果条件x满足的话,就输出x,如果不满足的话,就输出y
(1)np.mean //计算数组的均值
(2)np.sum //计算数组的和
(3)np.max //计算数组的最大值
(4)np.min //计算数组的最小值
(5)np.std //数组的平方差
(6)np.var //数组的方差
(7)np.argmax //将最大元素的下标进行输出
(8)np.argmin //将最小元素的下标进行输出
(9)np.cumsum //数组的累加和
(10)np.cumprod //数组的累乘
注意:多维的话要指定统计的维度,否则默认是全部维度上来做统计
arr = np.random.randn(3,4)#创建一个3行4列的数组 print(arr)#输出这个随机数组 np.where(arr>0,1,-1)#如果这个数组中的元素为大于0 的话,那就输出1,相反如果数组的元素的大小是小于0的话,那就输出-1
12.np.all和np.any
(1)all,全部满足条件
(2)any,至少有一个元素满足条件
arr=np.random.randn(2,3)#生成一个2行3列的矩阵 print(arr)#打印出这个矩阵 print(np.any(arr>0))#这个地方只要有一个元素是大于0的就输出True print(np.all(arr>0))#这个地方只有所有元素都大于0才会输出True
[[ 1.6030219 0.88871696 -0.09012569] [ 1.19059645 1.33357625 1.21061023]] True False
13.np.unique:找到唯一的值并返回排序结果
arr = np.array([[1,2,1],[2,3,4]]) print(arr)#这里生成一个2行3列的数组 print(np.unique(arr))#找到唯一值并返回结果
[[1 2 1] [2 3 4]]
[1 2 3 4]
14.读取文本文件
读取:np.loadtxt
#loadtxt filename='E:\\python\\codes\\codes\\presidential_polls.csv' data_array=np.loadtxt(filename, #文件名 delimiter=',', #分隔符 dtype=str, #数据类型 usecols=(0,2,3))#指定读取的列索引号 print(data_array,data_array.shape)#将数据读取进来,然后将数据的形状进行输出,数据的形状是10237行,3列
[['cycle' 'type' 'matchup'] ['2016' '"polls-plus"' '"Clinton vs. Trump vs. Johnson"'] ['2016' '"polls-plus"' '"Clinton vs. Trump vs. Johnson"'] ... ['2016' '"polls-only"' '"Clinton vs. Trump vs. Johnson"'] ['2016' '"polls-only"' '"Clinton vs. Trump vs. Johnson"'] ['2016' '"polls-only"' '"Clinton vs. Trump vs. Johnson"']] (10237, 3)
#loadtxt,明确指定每列数据的类型
filename='E:\\python\\codes\\codes\\presidential_polls.csv'#加载的文件
data_array=np.loadtxt(filename,#文件名
delimiter=',',#分隔符
skiprows=1,#跳过第一行
dtype={'names':('cycle','type','match'),
'formats':('i4','S15','S50')},#数据类型,数据格式:i代表int,4为4byte就是4位,S代表String,长度是15位,
usecols=(0,2,3))#指定读取列索引号
print(data_array,data_array.shape)#读取的结果是一维数组,每个元素是一个数组,而且元组里面的数据会根据我们指定的类型进行适当的读取
[(2016, b'"polls-plus"', b'"Clinton vs. Trump vs. Johnson"') (2016, b'"polls-plus"', b'"Clinton vs. Trump vs. Johnson"') (2016, b'"polls-plus"', b'"Clinton vs. Trump vs. Johnson"') ... (2016, b'"polls-only"', b'"Clinton vs. Trump vs. Johnson"') (2016, b'"polls-only"', b'"Clinton vs. Trump vs. Johnson"') (2016, b'"polls-only"', b'"Clinton vs. Trump vs. Johnson"')] (10236,)
二、SciPy
1.在Numpy库的基础上增加了众多的数学、科学及工程常用的函数库
2.线性代数、常微分求解、信号处理、图像处理、稀疏矩阵等
3.import scipy as sp
4.一般的数据处理numpy已经够用了
5.常用的统计函数在matplotlib部分讲解
6.subplot里结合scipy绘制统计图
(1)正太分布
(2)正太直方图
#在指定subplot作图 import scipy as sp from scipy import stats x=np.linspace(-5,15,50) print x.shape
三、数据可视化
1Matplotlib:用于创建出版质量图表的工具库
2.目的是为python构建一个Matlab式的绘画接口
3.import matplotlib.pyplot as plt
pyploy模块包含了常用的matplotlib API函数
4.figure:Matplotlib的图像均位于figure对象中
5.创建figure:plt.figure()
6.subplot,增加子图
fig.add_aubplot(a,b,c)
a,b表示将fig分割成为axb的区域
c表示当前选中要操作的区域,注意从1开始编号
plot绘图的区域是最后一次指定subplot的位置(jupyter里不能够正确显示)
直方图hist
散点图scatter
柱状图 bar
矩阵绘图 plt.imshow()
混淆矩阵,三个维度的关系
四、项目
1.项目目的:分析每个月的民意调查统计趋势
2.涉及的知识点:
(1)高阶函数:filter
(2)Numpy读取文本文件
(3)处理日趋格式数据
(4)Numpy的切片与索引
(5)Numpy的统计方法
(6)高级特性:列表推导式
(7)数据结构zip
(8)Matplotlib进行见的数据可视化
# coding:utf-8 ''' Created on Nov 20, 2016 @author: Bin Liang ''' # 引入必要的库 import numpy as np import datetime import matplotlib.pyplot as plt def is_convert_float(s): """ 判断一个字符串能否转换为float """ try: float(s) except: return False return True def get_sum(str_array): """ 返回字符串数组中数字的总和 """ # 去掉不能转换成数字的数据 cleaned_data = filter(is_convert_float, str_array) # 转换数据类型 float_array = np.array(cleaned_data, np.float) return np.sum(float_array) def run_main(): """ main function """ # 数据文件地址 filename = './presidential_polls.csv' ## Step1. 列名预处理 # 读取列名,即第一行数据 with open(filename, 'r') as f: col_names_str = f.readline()[:-1] # [:-1]表示不读取末尾的换行符'\n' # 将字符串拆分,并组成列表 col_name_lst = col_names_str.split(',') # 使用的列名 use_col_name_lst = ['enddate', 'rawpoll_clinton', 'rawpoll_trump','adjpoll_clinton', 'adjpoll_trump'] # 获取相应列名的索引号 use_col_index_lst = [col_name_lst.index(use_col_name) for use_col_name in use_col_name_lst] ## Step2. 读取数据 data_array = np.loadtxt(filename, # 文件名 delimiter=',', # 分隔符 skiprows=1, # 跳过第一行,即跳过列名 dtype=str, # 数据类型 usecols=use_col_index_lst) # 指定读取的列索引号 ## Step3. 数据处理 # 处理日期格式数据 enddate_idx = use_col_name_lst.index('enddate') enddate_lst = data_array[:,enddate_idx].tolist() # 将日期字符串格式统一,即'yy/dd/mm' enddate_lst = [enddate.replace('-', '/') for enddate in enddate_lst] # 将日期字符串转换成日期 date_lst = [datetime.datetime.strptime(enddate, '%m/%d/%Y') for enddate in enddate_lst] # 构造年份-月份列表 month_lst = ['%d-%02d' %(date_obj.year, date_obj.month) for date_obj in date_lst] month_array = np.array(month_lst) months = np.unique(month_array) ## Step4. 数据分析 # 统计民意投票数 # cliton # 原始数据 rawpoll rawpoll_clinton_idx = use_col_name_lst.index('rawpoll_clinton') rawpoll_clinton_data = data_array[:, rawpoll_clinton_idx] # 调整后的数据 adjpool adjpoll_clinton_idx = use_col_name_lst.index('adjpoll_clinton') adjpoll_clinton_data = data_array[:, adjpoll_clinton_idx] # trump # 原始数据 rawpoll rawpoll_trump_idx = use_col_name_lst.index('rawpoll_trump') rawpoll_trump_data = data_array[:, rawpoll_trump_idx] # 调整后的数据 adjpoll adjpoll_trump_idx = use_col_name_lst.index('adjpoll_trump') adjpoll_trump_data = data_array[:, adjpoll_trump_idx] # 结果保存 results = [] for month in months: # clinton # 原始数据 rawpoll rawpoll_clinton_month_data = rawpoll_clinton_data[month_array == month] # 统计当月的总票数 rawpoll_clinton_month_sum = get_sum(rawpoll_clinton_month_data) # 调整数据 adjpoll adjpoll_clinton_month_data = adjpoll_clinton_data[month_array == month] # 统计当月的总票数 adjpoll_clinton_month_sum = get_sum(adjpoll_clinton_month_data) # trump # 原始数据 rawpoll rawpoll_trump_month_data = rawpoll_trump_data[month_array == month] # 统计当月的总票数 rawpoll_trump_month_sum = get_sum(rawpoll_trump_month_data) # 调整数据 adjpoll adjpoll_trump_month_data = adjpoll_trump_data[month_array == month] # 统计当月的总票数 adjpoll_trump_month_sum = get_sum(adjpoll_trump_month_data) results.append((month, rawpoll_clinton_month_sum, adjpoll_clinton_month_sum, rawpoll_trump_month_sum, adjpoll_trump_month_sum)) print(results) months, raw_cliton_sum, adj_cliton_sum, raw_trump_sum, adj_trump_sum = zip(*results) ## Step5. 可视化分析结果 fig, subplot_arr = plt.subplots(2,2, figsize=(15,10)) # 原始数据趋势展示 subplot_arr[0,0].plot(raw_cliton_sum, color='r') subplot_arr[0,0].plot(raw_trump_sum, color='g') width = 0.25 x = np.arange(len(months)) subplot_arr[0,1].bar(x, raw_cliton_sum, width, color='r') subplot_arr[0,1].bar(x + width, raw_trump_sum, width, color='g') subplot_arr[0,1].set_xticks(x + width) subplot_arr[0,1].set_xticklabels(months, rotation='vertical') # 调整数据趋势展示 subplot_arr[1,0].plot(adj_cliton_sum, color='r') subplot_arr[1,0].plot(adj_trump_sum, color='g') width = 0.25 x = np.arange(len(months)) subplot_arr[1,1].bar(x, adj_cliton_sum, width, color='r') subplot_arr[1,1].bar(x + width, adj_trump_sum, width, color='g') subplot_arr[1,1].set_xticks(x + width) subplot_arr[1,1].set_xticklabels(months, rotation='vertical') plt.subplots_adjust(wspace=0.2) plt.show() if __name__ == '__main__': run_main()