频道栏目
首页 > 资讯 > Python > 正文

Python开发指南之数据分析教程

17-12-01        来源:[db:作者]  
收藏   我要投稿

NumPy基础:数组和矢量计算(基础 重中之重)

对于大部分数据分析应用而言,最关注的功能主要集中在:

·用于数据整理和清理、子集构造和过滤、转换等快速的矢量化数组运算。
·常用的数组算法,如排序、唯一化、集合运算等。
·高效的描述统计和数据聚合/摘要运算。
·用于异构数据集的合并/连接运算的数据对齐和关系型数据运算。
·将条件逻辑表述为数组表达式(而不是带有if-elif-else分支的循环)。
·数据的分组运算(聚合、转换、函数应用等)。第5章将对此进行详细讲解。
ps.没学过统计,看不懂 。后面再回顾
(作者建议使用import numpy as np 取代from numpy import * 严谨 规范)

NumPy的ndarry

ndarry字面上的意思即N维数组对象,元素必须是相同类型,这个数组可以对整块的数据执行一些数学运算 比如 data*10,data+data。元素的类型通过data.dtype可以查看。data.shape可以查看元组的大小如(2,3)代表2行三列。

创建一个ndarry

使用array函数接受一切序列型的对象(列表 嵌套序列),生成一个新的NumPy数组。比如:

import numpy as np
data1 = [5,7.5,8,0,1]
arr1 = np.array(data1)
arr1
#out:array([ 5. ,  7.5,  8. ,  0. ,  1. ])

其他构建方法及描述如下图:
这里写图片描述

需要注意的有两点:
np.zeros((3,4))创建多维时输入的是元组,有两个括号。
另外就是empty的数据并不是理想中的0,而是未初始化的值。

这里写图片描述

ndarray的数据类型

创建ndarray时也可以指明数据类型即dtype。可能会精度丢失,如下:

arr1 = np.array([1,2.5,3],dtype=np.int32)
arr1
#out:array([1,2,3])

这是一种很特殊的做法,直接指明ndarray的数据类型,这使得读写二进制数据流,集成低级语言代码(估计是直接读这个值即可知道数据类型,无需判断什么的)变得更简单。dtype的命名方式为类型+表示位长的数字。比如float64为双精度浮点占用8字节(64位)。支持的类型很多,常见的有int8/16/32/64 float16/32/64/128 bool complex64/128/256(复数) 甚至object 对象等!

既然支持这么多类型 那如果想转换类型怎么操作?当然是支持的啦,显示转换使用astype方法即可。如:

arr=np.array([1,2,3,4,5])
arr.dtype
#out:dtype('int64')

float_arr = arr.astype(np.float64)
float_arr.dtype
dtype('float64')

你也可以使用类型代码如下图所示,你甚至可以使用另一个ndarray的dtype来转换(float_arr = arr.astype(arr2.dtype)),当然转换失败会引发一个TypeError。

这里写图片描述

注意:调用astype无论如何都会创建出一个新的数组(原始数据的一份拷贝),即使新dtype跟老dtype相同也是如此。

警告:注意,浮点数(比如float64和float32)只能表示近似的分数值。在复杂计算中,由于可能会积累一些浮点错误,因此比较操作只能在一定小数位以内有效。

数组与标量之间的运算

数组很重要,因为它使你不用编写循环即可对数据执行批量运算。这通常就叫做矢量化(vectorization)。(就是不用那种for循环什么的一个一个的取数据了)大小相等的数组之间的任何算术运算都会将运算应用到元素级:

arr = np.array([[1.,2.,3.],[4.,5.,6.]])
arr 
out:array([[1.,2.,3.],[4.,5.,6.]])

arr*arr
out:array([[1.,4.,9.],[16.,25.,36.]])

什么1/arr arr**0.5(平方根) 就不列举了。

基本的索引和切片

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

arr[5:8]
out:array([5, 6, 7])

arr[5:8]=12
arr
out:array([ 0,  1,  2,  3,  4, 12, 12, 12,  8,  9])

如上所示,当你将一个标量值赋值给一个切片时(如arr[5:8]=12),该值会自动传播(也就说后面将会讲到的“广播”)到整个选区。跟列表最重要的区别在于,数组切片是原始数组的视图。这意味着数据不会被复制,视图上的任何修改都会直接反映到源数组上

这里写图片描述
作者说你可能会感到很诧异,确实很诧异。。。(原因是NumPy是用来处理大数据,所以它尽可能的避免去复制耗费性能和内存)

如果你真的要复制的话使用arr[5:8].copy()

高纬度的如何索引?
这里写图片描述

切片索引

arr2d
out:array([[1,2,3],[4,5,6],[7,8,9]])

arr2d[:2]
#左闭右开 [:2]为0,1,不包含2
out:array([[1,2,3],[4,5,6]])

arr2d([:2,1:])
#与前面的多个索引一样,对第一维取[:2],第二维度取[1:]
out:array([2,3],[5,6])

arr2d[1,:2]
#取一维的第1个 再去取该元素的第[0,2)元素
out:array([4,5])

arr2d[:,:1]
out:array([[1],[4],[7]])
#对其赋值也会扩散到整个选取

布尔型索引

names = np.array(['Bob','Joe','Will','Bob','Will','Joe','Joe'])
names == 'Bob'
out:array([True,False,False,True,False,False],dtype=bool)
data[names == 'Bob']
out:array([[-0.048,0.5433,-0.2349,1.2792],[2.1452,0.8799,-0.0523,0.0672]])
#把ture的选出来

当然这种索引还可以与切片整数等等混合来使用。

data[names == 'Bob',2:]
#我的理解是第一维用names == 'Bob'来索引,第二维度用2:来索引。这样可能更好理解和记忆一点。
Out:array([[-0.2349,1.2792],[-0.0523,0.0672]])

当然 你甚至还可以这样用:data[-(names == ‘Bob’)]
使用&,|布尔运算符来这样用:mask = (names == ‘Bob’) | (names == ‘Will’)

为了使data中所有负值设为0,可以用如此简单的方式:
data[data < 0 ] = 0

花式索引

arr = np.empty((8,4))
for i in range(8):
    arr[i] = i
arr
out:array([[0.,0.,0.,0.],
            [1.,1.,1.,1.],
            [2.,2.,2.,2.],
            [3.,3.,3.,3.],
            ....#偷懒
            [7.,7.,7.,7.]])

当你要以特定顺序选取时:

arr[[4,3,-1]]
out:array([[4.,4.,4.,4.],
            [3.,3.,3.,3.],
            [7.,7.,7.,7.]])
#负数从末尾开始算

花式索引比较特殊的地方:
这里写图片描述

可以用下面方法 得到这个结果:
这里写图片描述

另外:花式索引与切片不同,它总是复制数据到新的数组中。

总结:学习了NumPy的ndarry从创建到各种取数据,你能察觉到它为了方便处理大数据,无论是赋值,修改,还是取数据都做了很多的操作,极其的方便。

相关TAG标签
上一篇:Kafka开发教程之消息队列解析
下一篇:kafka0.8--0.11各个版本特性预览介绍
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站