利用Python进行数据分析复现(三)

第4章 numpy基础:数组和矢量计算

使用numpy计算比纯python计算快10到100倍(甚至更快),并且使用内存更少。

NumPy的ndarray:一种多维数组对象

numpy的N维数组对象(ndarray),该对象是一个快速而灵活的大数据集容器。

import numpy as np
data=np.random.randn(2,3)
data
array([[ 0.00668162,  0.45723418,  0.0438548 ],
       [-2.23335801, -0.39107094, -0.25007822]])
data*10
array([[  0.06681624,   4.57234183,   0.43854801],
       [-22.33358006,  -3.91070938,  -2.5007822 ]])
data+data
array([[ 0.01336325,  0.91446837,  0.0877096 ],
       [-4.46671601, -0.78214188, -0.50015644]])

每个ndarray都有一个shape(一个表示各维度大小的元组)和一个dtype(一个用于说明数组数据类型的对象)

data.shape
(2, 3)
data.dtype
dtype('float64')

创建ndarray

使用array函数,接受将一切序列型的对象(包括其他数组),然后产生一个新的含有传入数据的numpy数组。同时可以把嵌套序列转为一个多维数组。

data1=[1,2,3,4,9.4]
arr1=np.array(data1)
arr1
array([1. , 2. , 3. , 4. , 9.4])
data2=[[1,2,3],[4.5,4,5]]
arr2=np.array(data2)
arr2
array([[1. , 2. , 3. ],
       [4.5, 4. , 5. ]])

除非特别说明,np.array会尝试为新建的这个数组推断出一个较为合适的数据类型。数据类型保存在一个特殊的dtype对象中。
numpy还可以建立一些特殊数组,例如:ones(全1)、zeros(全0)。empty可以创建一个没有具体值的数组。

np.zeros(10)
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
np.ones((2,3))
array([[1., 1., 1.],
       [1., 1., 1.]])
np.empty((2,3,4))
array([[[2.05833592e-312, 2.05833592e-312, 1.29441743e-312,
         1.03977794e-312],
        [1.06099790e-312, 1.08221785e-312, 1.10343781e-312,
         1.20953760e-312],
        [1.10343781e-312, 2.12199580e-313, 2.41907520e-312,
         1.03977794e-312]],

       [[2.33419537e-312, 9.76118064e-313, 2.41907520e-312,
         2.05833592e-312],
        [8.48798317e-313, 2.05833592e-312, 2.05833592e-312,
         8.70018275e-313],
        [2.05833592e-312, 2.41907520e-312, 9.80058112e+252,
         1.23971686e+224]]])
np.arange(15)
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14])

一些常见的数组创建函数如下表。一般数据类型在没有特别说明的情况下,都是float64(浮点数)。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-VfeYa2QQ-1579187132805)(attachment:16.png)]

ndarray的数据类型

dtype含有ndarray将一块内存解释为特定数据类型所需的信息。常见的NumPy数据类型有:


17.png

可以通过astype方法明确地把一个数组从一个dtype转到另一个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')
arr3=arr1.astype(np.int32)
arr3.dtype
dtype('int32')

numpy数组的运算

大小相等(shape相同)的数组之间的任何算术运算都会将运算应用到元素级。
会降到对应元素之间的算术运算。
对于标量(非数组,单独数字)与数组的算术运算将标量传播到各个元素。
对于shape相同的数组之间的比较,会产出布尔数组。

arr=np.array([[1.,2.,3.],[4.,5.,6.]])
arr*arr
array([[ 1.,  4.,  9.],
       [16., 25., 36.]])
arr-arr
array([[0., 0., 0.],
       [0., 0., 0.]])
arr**2
array([[ 1.,  4.,  9.],
       [16., 25., 36.]])
1/arr
array([[1.        , 0.5       , 0.33333333],
       [0.25      , 0.2       , 0.16666667]])
arr2=np.array([[2.,3.,4.],[1.,2.,10.]])
arr2>arr1
array([[ True,  True,  True],
       [False, False,  True]])

基本的索引和切片

对于一维数组的切片和python列表的功能差不多。
需要注意的是,对于数组的切片的修改,也会直接反应到原数组中,源数组的数据类型也会发生变化。

arr=np.arange(10)
arr
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
arr[1:3]
array([1, 2])
arr[4:6]=13
arr
array([ 0,  1,  2,  3, 13, 13,  6,  7,  8,  9])
arr_sl=arr[3:6]
arr_sl[2]=999
arr
array([  0,   1,   2,   3,  13, 999,   6,   7,   8,   9])

对于多维数组,进行元素选择的时候,只需要逐层向下传递就行。
在二维数组中,轴0作为行,轴1作为列。(axis=0即为行,axis=1即为列)。
数组或标量值都是可以被赋值为数组中的某部分。

arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
arr3d[0]
array([[1, 2, 3],
       [4, 5, 6]])
old_values = arr3d[0].copy()
arr3d[0] = 42
arr3d
array([[[42, 42, 42],
        [42, 42, 42]],

       [[ 7,  8,  9],
        [10, 11, 12]]])
arr3d[0] = old_values
arr3d
array([[[ 1,  2,  3],
        [ 4,  5,  6]],

       [[ 7,  8,  9],
        [10, 11, 12]]])

就切片而言,一维数组切片和python语法差别不大。二维数组的切片,其是按着某个轴方向进行切片的。
切片中的多轴取值如下例:


18.png
arr2d=np.array([[1,2,3],[4,5,6],[7,8,9]])
arr2d[:2]
#沿着第一个轴(第0轴)进行切片。
#注意,“只有冒号”表示选取整个轴,因此你可以像下面这样只对高维轴进行切片。
array([[1, 2, 3],
       [4, 5, 6]])

布尔型索引

利用true或者false进行选择数据。布尔型数组的长度必须跟被索引的轴长度一致。要选择除"Bob"以外的其他值,既可以使用不等于符号(!=),也可以通过~对条件进行否定。选取这三个名字中的两个需要组合应用多个布尔条件,使用&(和)、|(或)之类的布尔算术运算符。

names = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
data = np.random.randn(7, 4)
names == 'Bob'
array([ True, False, False,  True, False, False, False])
data
array([[ 1.88604910e+00, -1.09239246e+00,  7.36955312e-01,
         6.21962781e-01],
       [-8.94589801e-01, -7.04479134e-01,  6.15735344e-01,
         4.17365984e-01],
       [-1.88309621e+00,  1.48204259e+00, -1.05637845e-01,
        -1.47304673e+00],
       [-3.27432236e-01,  2.47418588e-03,  6.11339801e-01,
        -9.02064313e-01],
       [-2.30341292e+00,  3.13932432e-01,  1.25433341e+00,
        -7.04365322e-02],
       [ 1.10938161e+00,  6.42370960e-01,  1.09503863e+00,
        -2.70052944e-01],
       [ 1.14600475e+00,  1.34853669e+00,  1.38460778e-01,
        -2.01624321e-03]])
data[names == 'Bob']
array([[ 1.8860491 , -1.09239246,  0.73695531,  0.62196278],
       [-0.32743224,  0.00247419,  0.6113398 , -0.90206431]])
data[names == 'Bob', 2:]
array([[ 0.73695531,  0.62196278],
       [ 0.6113398 , -0.90206431]])
names != 'Bob'
array([False,  True,  True, False,  True,  True,  True])
data[~(names == 'Bob')]
array([[-8.94589801e-01, -7.04479134e-01,  6.15735344e-01,
         4.17365984e-01],
       [-1.88309621e+00,  1.48204259e+00, -1.05637845e-01,
        -1.47304673e+00],
       [-2.30341292e+00,  3.13932432e-01,  1.25433341e+00,
        -7.04365322e-02],
       [ 1.10938161e+00,  6.42370960e-01,  1.09503863e+00,
        -2.70052944e-01],
       [ 1.14600475e+00,  1.34853669e+00,  1.38460778e-01,
        -2.01624321e-03]])
con=names=='Bob'
data[~con]
array([[-8.94589801e-01, -7.04479134e-01,  6.15735344e-01,
         4.17365984e-01],
       [-1.88309621e+00,  1.48204259e+00, -1.05637845e-01,
        -1.47304673e+00],
       [-2.30341292e+00,  3.13932432e-01,  1.25433341e+00,
        -7.04365322e-02],
       [ 1.10938161e+00,  6.42370960e-01,  1.09503863e+00,
        -2.70052944e-01],
       [ 1.14600475e+00,  1.34853669e+00,  1.38460778e-01,
        -2.01624321e-03]])
mask = (names == 'Bob') | (names == 'Will')
mask
array([ True, False,  True,  True,  True, False, False])
data[mask]
array([[ 1.8860491 , -1.09239246,  0.73695531,  0.62196278],
       [-1.88309621,  1.48204259, -0.10563785, -1.47304673],
       [-0.32743224,  0.00247419,  0.6113398 , -0.90206431],
       [-2.30341292,  0.31393243,  1.25433341, -0.07043653]])
data[data < 0] = 0
data
array([[1.8860491 , 0.        , 0.73695531, 0.62196278],
       [0.        , 0.        , 0.61573534, 0.41736598],
       [0.        , 1.48204259, 0.        , 0.        ],
       [0.        , 0.00247419, 0.6113398 , 0.        ],
       [0.        , 0.31393243, 1.25433341, 0.        ],
       [1.10938161, 0.64237096, 1.09503863, 0.        ],
       [1.14600475, 1.34853669, 0.13846078, 0.        ]])
data[names != 'Joe'] = 7
data
array([[7.        , 7.        , 7.        , 7.        ],
       [0.        , 0.        , 0.61573534, 0.41736598],
       [7.        , 7.        , 7.        , 7.        ],
       [7.        , 7.        , 7.        , 7.        ],
       [7.        , 7.        , 7.        , 7.        ],
       [1.10938161, 0.64237096, 1.09503863, 0.        ],
       [1.14600475, 1.34853669, 0.13846078, 0.        ]])

数组转置和轴对换

数组转置有transpose方法,也有一个特殊T属性.

arr=np.arange(15).reshape((3,5))
arr
array([[ 0,  1,  2,  3,  4],
       [ 5,  6,  7,  8,  9],
       [10, 11, 12, 13, 14]])
arr.T
array([[ 0,  5, 10],
       [ 1,  6, 11],
       [ 2,  7, 12],
       [ 3,  8, 13],
       [ 4,  9, 14]])
np.dot(arr.T,arr)
array([[125, 140, 155, 170, 185],
       [140, 158, 176, 194, 212],
       [155, 176, 197, 218, 239],
       [170, 194, 218, 242, 266],
       [185, 212, 239, 266, 293]])

对于高维数组,transpose需要得到一个由轴编号组成的元组才能对这些轴进行转置。
arr.transpose((1,0,2)) 表示第一轴被换成原数组的第二个维度,第二个轴被换成原数组的第一个维度数组,最后一个轴不变。

arr=np.arange(12).reshape((2,2,3))
arr
array([[[ 0,  1,  2],
        [ 3,  4,  5]],

       [[ 6,  7,  8],
        [ 9, 10, 11]]])
arr.transpose((1,0,2))
array([[[ 0,  1,  2],
        [ 6,  7,  8]],

       [[ 3,  4,  5],
        [ 9, 10, 11]]])

通用函数:快速的元素级数组函数

可以同时对数组的整体数据进行函数变换。例如sqrt(平方)和exp(e的指数值);add(求多个数组的和)或maximum(多个数组中元素级别最大的元素)。modf函数,可以分离浮点数数组的小数和整数部分。
还有一些函数如下:


19.png
20.png
arr = np.random.randn(7) * 5
remainder, whole_part = np.modf(arr)
remainder
array([-0.17048277, -0.85976085,  0.54241456, -0.10808041,  0.4622122 ,
        0.89957455,  0.38456908])
whole_part
array([-10.,  -3.,   8.,  -0.,   4.,   1.,   5.])

利用数组进行数据处理

numpy矢量化数组运算速度要比等价的纯Python方式快上一两个数量级。

p=np.arange(-5,5,0.01)
x,y=np.meshgrid(p,p)#np.meshgrid函数接受两个1维数组,并产生两个二维矩阵(对应于两个数组中所有的(x,y)对)
y
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.97,  4.97,  4.97, ...,  4.97,  4.97,  4.97],
       [ 4.98,  4.98,  4.98, ...,  4.98,  4.98,  4.98],
       [ 4.99,  4.99,  4.99, ...,  4.99,  4.99,  4.99]])
z=np.sqrt(x**2+y**2)
import matplotlib.pyplot as plt
plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()
plt.title("Image plot of $\sqrt{x^2 + y^2}$ for a grid of values")
Text(0.5,1,'Image plot of $\\sqrt{x^2 + y^2}$ for a grid of values')
plt.imshow(z, cmap=plt.cm.gray); plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x12cf75f8>
output_67_1.png

将条件逻辑表述为数组运算

np.where函数是三元表达是 x if condition else y的矢量化版本。np.where的第2个和第三个参数不必是数组,它们都可以是标量值。在数据分析工作中,where通常用于根据另一个数组而产生一个新的数组。

xarr = np.array([1.1, 1.2, 1.3, 1.4, 1.5])
yarr = np.array([2.1, 2.2, 2.3, 2.4, 2.5])
cond = np.array([True, False, True, True, False])
result = [(x if c else y)
          for x, y, c in zip(xarr, yarr, cond)]
result
[1.1, 2.2, 1.3, 1.4, 2.5]
result = np.where(cond, xarr, yarr)
result
array([1.1, 2.2, 1.3, 1.4, 2.5])

数学和统计方法

sum、mean以及标准差std等聚合计算。对于一维数组而言,arr.mean(1)是“计算行的平均值”,arr.sum(0)是“计算每列的和”。arr.cumsum()为arr数组的累加数组。


21.png

使用布尔数组进行数据选择。

True表示1,0为False.

排序

和python中的sort方法一样。np.sort返回的是数组是已排序副本。

唯一化以及其它的集合逻辑

通过np.unique方法可以找出数组中的唯一值并返回已排序的结果。


22.png

用于数组的文件输入输出

numpy保存的文件是npy文件。np.save(保存数据文件)和np.load(读取数据文件)是读写磁盘数组数据的两个主要函数。

线性代数

x = np.array([[1., 2., 3.], [4., 5., 6.]])
y = np.array([[6., 23.], [-1, 7], [8, 9]])
#x.dot(y)等价于np.dot(x, y)
x.dot(y)
array([[ 28.,  64.],
       [ 67., 181.]])
np.ones(3)
array([1., 1., 1.])
np.dot(x, np.ones(3))
array([ 6., 15.])

numpy.linalg中有1组标准的矩阵分解运算以及诸如求逆和行列式之类的函数。


23.png

伪随机数生成

随机数的生成和随机种子相关,


24.png
#随机漫步的计算。
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,914评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,935评论 2 383
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,531评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,309评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,381评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,730评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,882评论 3 404
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,643评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,095评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,448评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,566评论 1 339
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,253评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,829评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,715评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,945评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,248评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,440评论 2 348

推荐阅读更多精彩内容