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位的数据
维度个数: 2
各维度大小: (2, 3)
数据类型: float64
In [ ]:
创建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
[[ 1.29110422  0.82802396  1.73696831 -0.65269742]
 [ 0.96577295  0.73177632  0.64707468  2.17183827]
 [ 1.38970299 -1.59210536  0.80436783  0.45894793]]
Out[53]:
array([[ 1,  1,  1, -1],
       [ 1,  1,  1,  1],
       [ 1, -1,  1,  1]])

#常用的统计方法
arr = np.arange(10).reshape(5,2)#创建一个0-9的随机数组,将其变换成5行两列的数组
print(arr)#输出所有的元素

print(np.sum(arr))#求出整个矩阵的和
print(np.sum(arr,axis=0))#统计在0方向上的
print(np.sum(arr,axis=1))#在相反方向上进行求和

#现将矩阵进行转置操作

[[0 1]
 [2 3]
 [4 5]
 [6 7]
 [8 9]]
#求出整个矩阵的和 45
#求出在竖直方向,每一列的和 [20 25]
#求出沿每一行方向每一行的和 [ 1 5 9 13 17]

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()

 

posted @ 2018-10-02 21:59  stone1234567890  阅读(709)  评论(0编辑  收藏  举报