本节概要
Numpy详解
安装
Numpy的安装已经不想多说。。在确保pip或pip3的路径被添加到系统环境变量里面之后,就可以直接用下面语句进行安装。
pip install numpy or pip3 install numpy
当然PyCharm里面也可以用搜索的方式安装。
Numpy是什么?
Numpy(Numerical Python的简称)是高性能科学计算和数据分析的基础包。是很多高级工具的构建基础。部分功能如下:
1、ndarray,一个具有矢量算术运算和复杂关闭能力的快速节省空间的多维数组
2、用于对整组数据进行快速运算的标准数学函数(无需编写循环!!!!)
3、用于读写磁盘数据的工具以及用于操作内存映射文件的工具。
4、线性代数,随机数以及傅里叶变换功能
5、用于继承C、C++、Fortran等语言编写的代码的工具
最后一点也就是从生态系统角度来看最重要的一点,由于Numpy提供了一个简单易用的C的API,因此很容易将数据传递给由低级语言编写的外部库,外部库也能以NumPy数组的形式将数据返回给Python。这个功能使Python成为一种包装C/C++/Fortran历史代码库的选择,并使被包装库有一个动态的,易用的接口。
a、NumPy的ndarray (多维数组对象)
ndarra对象是一个快速灵活的大数据集容器。
创建
import numpy as np
data1 = [6, 7.5, 8, 0, 1]
arr1 = np.array(data1) data2 = [[1,2,3],[4,5,6]]
arr2 = np.array(data2) print(arr2.ndim) # dimension 维度
print(arr2.shape) # 多维行列参数
print(arr2.dtype) # 数据类型
其它创建数组:zeros 和 ones 可以创建指定长度或形状的全0或者全1数组
arr3 = np.zeros((3, 6))
arr4 = np.ones(10)
arr5 = np.empty((10,2)) ==> 并不会返回全0数组结构。很多情况下都是返回未初始化的垃圾值 arr6 = np.arange(15) ==> [ 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14]
b、dtype
设置:arr1 = np.array([1,2,3], dtype=np.float64)
转换:arr2 = arr1.astype(np.float32)
如果浮点型转换成整型,小数位会被截断;如果写的是float,而不是np.float64,NumPy会聪明的将Python类型映射到等价的dtype上
NumPy 如此强大、灵活的原因之一就是dtype,多数情况下,它直接映射到相应的机器表示,这使得"读写磁盘上的二进制数据流" 以及 "集成低级语言代码(c,Fortran)"等工作变得简单
dtype的另类用法:
int_arr = np.arange(10)
calibers = np.array([.22, .270, .357, .380, .44, .50], dtype=np.float64)
int_arr.astype(calibers.dtype) ==> array([0., 1., 2., 3., ....])
也可以用简介的类型代码来表示dtype:
empty_unit32 = np.empty(8, dtype='u4') ==> dtype=unit32
c、数组跟标量的运算(广播 运算)
arr = np.array([[1,2,3],[4,5,6]]) arr * arr ==> [[1,4,9],[16,25,36]]
arr - arr ==> [[0,0,0],[0,0,0]]
1/arr arr ** 0.5 同理
d、索引与切片
arr = np.array(10) ==> [0,1,2,3,4,5,6,7,8,9] arr[5:8] ==> [5,6,7]
arr[5:8] = 12 ==> [12,12,12] 广播赋值
这里我们再看一下原始数组
arr ==> [0,1,2,3,4,12,12,12,8,9]
跟python最主要的区别就是,NumPy数组的切片是原始数组的视图。也就意味着数组不会被复制,视图上的任何修改都会直接反映到源数组上
arr_slice = arr[5:8]
arr_slice[1] = 12345 arr ==> [0,1,2,3,4,12,12345,12,8,9]
arr_slice[:] = 64 arr ==> [0,1,2,3,4,64,64,64,8,9]
如果不想修改到源数组,真正要的是一份副本,则需要使用copy(深copy)
arr[5:8].copy()
对于二维数组,各索引位置上的元素不再是标量而是一维数组
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr[2] ==> [7,8,9] 维度为2的数组或者维度索引为2的数组
访问二维数组的元素:
arr[0][2]
arr[0,2]
这是两种等价的方式
多维数组索引
arr = np.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
arr[0] ==> [[1,2,3],[4,5,6]]
标量值跟数组都可以赋值给arr[0]
old_value = arr[0].copy()
arr[0] = 1 ==> arr([[[1,1,1],[1,1,1]],[[7,8,9],[10,11,12]]])
arr[0] = old_value ==> arr([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
以此类推
arr[1,0] ==> [7,8,9]
切片索引
arr = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr[:2] ==> [[1,2,3],[4,5,6]]
arr[:2,1:] ==> [[2,3],[5,6]]
arr[1,:2] ==> [4,5]
arr[2,:1] ==> [7]
只有冒号表示选取整个轴
arr[:,:1] ==>[[1],[4],[7]]
e、布尔型索引
总是创建数据副本,即使是返回一模一样的数组也是
names = np.array(['dandy','bob','renee','will','crystal','sam','sam'])
data = random.randn(7,4) names=='dandy' ==> [ True False False False False False False]
data[names=='dandy'] ==> [[ 0.64963011 -0.35657571 0.78491052 -0.78356789]] 布尔数组的长度跟被索引的轴的长度必须一致
同时布尔值数组跟切片,整数可以混用
data[names=='dandy', 2:] ==>[[xx,xx],[xx,xx]]
data[names=='dandy', 3] ==>[xx,xx] dandy以外的其他值:!= 或者- (条件否定)
data[names != 'dandy']
data[-(names == 'dandy')]
与或非 ==> &, |, ! (关键字and or无效)
mask = (names == 'dandy')|(names == 'bob')
data[mask]
布尔型数组设置值
data[data>0] = 0 ==>数组中所有大于零的全部赋值为0
data[names!='dandy'] = 7 ==>数组布尔索引并赋值
f、花式索引
复制数据到新数组中
arr = np.empty((8,4))
for i in range(8):
arr[i] = i
arr([[0,0,0,0],...,[7,7,7,7]]) arr[[4,3,0,6]] 取arr的4,3,0,6行 [[4,4,4,4],[3,3,3,3],[0,0,0,0],[6,6,6,6]]
负数索引 则从末尾开始取值
重塑
arr = np.arange(32).reshape((8,4)) ==> 重塑 [[ 0 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]
[12 13 14 15]
[16 17 18 19]
[20 21 22 23]
[24 25 26 27]
[28 29 30 31]]
arr[[1,5,7,2],[0,3,1,2]] ==> (1,0),(5,3),(7,1),(2,2)位置坐标
输出: [4,23,29,10] arr[[1,5,7,2]][:,[0,3,1,2]]
输出:
[[ 4 7 5 6]
[20 23 21 22]
[28 31 29 30]
[ 8 11 9 10]]
也可以用np.ix_函数来去数组
arr[np.ix_([1,5,7,2],[0,3,1,2])]
[[ 4 7 5 6]
[20 23 21 22]
[28 31 29 30]
[ 8 11 9 10]]
g、数组转置跟轴对换 (返回的是源数据的视图)
arr = np.arange(15).reshape((3,5))
转置 arr.T
矩阵内积:
np.dot(arr.T, arr)
高维数组
arr = np.arange(16).reshape((2,2,4))
[[[ 0 1 2 3]
[ 4 5 6 7]] [[ 8 9 10 11]
[12 13 14 15]]]
轴对换
arr = np.arange(16).reshape((2,2,4))
print(arr.transpose((1,0,2)))
[[[ 0 1 2 3]
[ 8 9 10 11]] [[ 4 5 6 7]
[12 13 14 15]]]
转置
arr.swapaxes(1,2)
[[[ 0 4]
[ 1 5]
[ 2 6]
[ 3 7]] [[ 8 12]
[ 9 13]
[10 14]
[11 15]]]
h、通用函数
arr = np.arange(10)
np.sqrt(arr) => 平方根
np.exp(arr) => 指数幂(e) maximum
x = randn(8)
y = randn(8)
np.maximum(x,y) ==> 返回元素级最大值的一维数组 arr = randn(7)*5
np.modf(arr) ==> 返回整数数组跟小数数组
i、数组的数据处理
points = np.arange(-5,5,0.01)
meshgrid接受两个一维数组,产生两个二维数组
xs,ys = np.meshgrid(points,points)
求值运算
z = np.sqrt(xs**2, ys**2) ==> 因xs等于ys;则z=根号2xs
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, False, False, False])
当cond为True,选取xarr;false则yarr
result = np.where(cond, xarr, yarr) => [1.1,2.2,2.3,2.4,2.5]
where的第二个跟第三个参数不必是数组,标量值也可以
arr = randn(4,4)
np.where(arr>0,2,-2) => 随机数组大于0的为2,小于0的为-2
np.where(arr>0,2,arr) => 随机数组大于0的为2,小于0的不变
j、数学跟统计方法
arr = np.random.randn(5,4)
求平均值2种方法
arr.mean()
np.mean(arr)
sum
arr.sum()
mean跟sum这类函数可以接收一个参数axis(用于计算该轴向上的统计值)
axis不设置 对m*n个数求值,返回一个实数
axis = 0 关注列,压缩成一行 对各列求值,返回1*n矩阵
axis = 1 关注行,压缩成一列 对各行求值,返回m*1矩阵
cumsum & cumprod (不聚合,产生一个由中间结果组成的数组)
arr = np.array([[0,1,2],[3,4,5],[6,7,8]])
arr.cumsum(0) ==> 行往下 累加
结果 [[ 0 1 2]
[ 3 5 7]
[ 9 12 15]]
arr.cumprod(1) ==> 列往右 累乘
结果 [[ 0 0 0]
[ 3 12 60]
[ 6 42 336]]
k、布尔型数组方法
arr = randn(100)
(arr>0).sum() ==> 统计正值
bools = np.array([True, False, False, False])
bools.any() 测试数组是否存在True
结果 True
bools.all() 数组是否全部都是True any 跟 all 也能用于非布尔型数组,非0元素将被当做True
l、排序
产生数组副本
一维数组
arr = randn(8)
arr.sort()
二维数组
arr = randn(5,3)
arr.sort(1) ==> 关注行内排序 选取分位数
large_arr =randn(1000)
large_arr.sort() ==> 排序
large_arr[int(0.05 * len(large_arr))] 5%分位数
m、唯一性及其他逻辑
names = np.array(['dandy','bob','renee','will','crystal','sam','sam'])
np.unique(names) ==> 去重,string,int都可以
我们知道python的列表是自动去重的,所以
sorted(set(names))
测试一个数组值在另一个数组中的成员资格,返回布尔数组
values = np.array([6,0,0,3,2,5,6])
np.in1d(values, [2,3,6])
array([True,False.....,True])
n、数组文件的输入输出
数组文件
保存
arr = np.arange(10)
np.save('test', arr)
没有扩展名.npy,会自动补上
读取
arr = np.load('test') ==> 获得的是一个数组
压缩
np.savez 类型(npz) 可以将对多个数组保存到一个压缩文件中,将数组以关键字形式传入即可:
np.savez('array_archive.npz', a=arr1, b=arr2)
加载.npz文件时,你会得到一个类似字典的对象,该对象会对各个数组延迟加载
arch = load('array_archive.npz')
arch['b'] ==> arr2数组对象 文本文件
arr = np.loadtxt('arr_ay.txt', delimiter=",") 逗号分隔的二维数组
np.savetxt跟上面的差不多
np.savetxt执行的是相反操作,将数组写到以某种分隔符隔开的文本文件中。getfromtxt跟loadtxt差不多,只不过它面向的是结构化数组和缺失数据处理
o、线性代数
线性代数是任何数组库的重要组成部分。通过*对两个二维数组相乘得到的是一个元素级的积。因此,Numpy提供了一个用于矩阵乘法的dot函数
x = np.array([[1.,2.,3.],[4.,5.,6.,]])
y = np.array([[6.,23.],[-1,7],[8,9]])
print(x)
print(y)
print(x.dot(y)) # 相当于np.dot(x,y)
一个二维数组跟一个大小合适的一维数组的矩阵点积运算之后得到一个一维数组:
np.dot(x, np.ones(3)) [ 6. 15.]
numpy.linalg中有一组标准的矩阵分解运算以及诸如求逆和行列式之类的东西。跟MATLAB和R语言所使用的的是相同的行业标准级的Fortran库,如:BLAS、LAPACK、IntelMKL
实例:
from numpy.linalg import inv,qr
X = np.random.randn(5,5)
mat = X.T.dot(X) # X和X的转置矩阵的点积
print(inv(mat)) # 逆矩阵
输出:
[[ 2.75183656 -2.3478836 -2.61320548 -1.04234063 0.93357253]
[-2.3478836 2.74218612 2.3537533 1.45492871 -1.03972442]
[-2.61320548 2.3537533 2.75010067 1.21183773 -1.0909068 ]
[-1.04234063 1.45492871 1.21183773 1.35983185 -0.95369447]
[ 0.93357253 -1.03972442 -1.0909068 -0.95369447 0.90587929]]
继续:(就不要问为什么逆矩阵乘本身得到这个结果了。。。看线性代数去吧)
print(mat.dot(inv(mat)))
q, r = qr(mat) # 至于qr分解,暂时还没看懂什么意思0.0,楼主也在研究线性代数
print(r)
输出:
[[ 1.00000000e+00 6.93889390e-18 1.80411242e-16 -2.42861287e-17
0.00000000e+00]
[ -5.55111512e-17 1.00000000e+00 4.44089210e-16 1.38777878e-17
3.88578059e-16]
[ 0.00000000e+00 0.00000000e+00 1.00000000e+00 -2.22044605e-16
-4.44089210e-16]
[ 1.66533454e-16 -1.11022302e-16 0.00000000e+00 1.00000000e+00
-2.22044605e-16]
[ -2.22044605e-16 -2.22044605e-16 0.00000000e+00 3.33066907e-16
1.00000000e+00]]
[[-11.19953315 -11.83491161 8.73455769 1.36529151 -2.31283099]
[ 0. -6.4372489 4.65628801 -1.1686483 -3.36988755]
[ 0. 0. -9.98879178 5.88445016 9.82750912]
[ 0. 0. 0. -5.78724596 2.23174313]
[ 0. 0. 0. 0. 1.54121747]]
p、随机数生成
numpy.random模块对Python内置的random进行了补充,增加了一些用于高效生成多种概率分布的样本值函数。例如,你可以用normal来得到一个标准正态分布的4*4样本数组:
samples = np.random.normal(size=(4, 4))
print(samples)
[[-0.14196335 -0.07402951 -0.02838652 -1.67057212]
[ 0.10550666 0.55619815 0.08196452 -0.03504712]
[ 0.23530906 0.05405759 0.87008255 0.52502829]
[ 0.22493807 0.25954076 1.57337562 0.05819842]]
而Python内置的random模块则只能一次生成一个样本值。从下面的测试结果可以看出,如果需要产生大量样本值,numpy.random快了不止一个数量级:
from random import normalvariate
N = 10000
%timeit samples = [normalvariate(0, 1) for _ in xrange(N)]
%timeit np.random.normal(size=N)
实例:随机漫步
从0开始,步长1和-1出现的概率相等。
为了展示出一个对比度,我们先用纯python写:
import random
position = 0
walk = [position]
steps = 1000
for i in range(steps):
step = 1 if random.randint(0, 1) else -1
position += step
walk.append(position)
这时我们用numpy.random模块一次性随机产生1000个结果,将其分别设置为1和-1,然后求累积和:
import numpy as np
nsteps = 1000 # 定义步数
draws = np.random.randint(0, 2, size=nsteps) # 生成随机数
steps = np.where(draws>0, 1, -1) # 三元运算
walk = steps.cumsum() # 累加
有了这些数据,就可以做一些统计工作了,比如求取最大最小值:
walk.min() # 最小值
walk.max() # 最大值
现在我们统计一个有点难度,复杂的统计任务,首次穿越时间,即随机漫步过程中第一次到达长度10(绝对值),需要多久?
思路: np.abs(walk) > 10可以得到一个布尔型数组,表示的是距离是否大于等于10;我们需要的是第一个达到的索引。可以用argmax来解决这个问题,它返回的是该布尔型数组第一个最大值的索引(True就是最大值):
(np.abs(walk) >= 10).argmax()
这里的argmax并不是很高效,因为无论如何它都会对数组进行完全扫描,其实没这个必要。
一次模拟多个随机漫步
import numpy as np
nwalks = 5000
nsteps = 1000 # 定义步数
draws = np.random.randint(0, 2, size=(nwalks, nsteps)) # 生成随机数 数组
steps = np.where(draws>0, 1, -1) # 三元运算
walks = steps.cumsum(1) # 行累加
计算所有随机漫步过程中的最大值,最小值:
walks.max()
walks.min()
我们现在来计算下达到30步距离的最小穿越时间,因为不是所有的随机漫步都会满足条件,我们需要一个any方法来检验
import numpy as np
nwalks = 5000
nsteps = 1000 # 定义步数
draws = np.random.randint(0, 2, size=(nwalks, nsteps)) # 生成随机数 数组
steps = np.where(draws>0, 1, -1) # 三元运算
walks = steps.cumsum(1) # 行累加 hits = (np.abs(walks) >= 30).any(1) # 关注每行
print(hits)
# 输出结果[ True True True ..., True True False] print(hits.sum()) # 达到30或-30的总数量
# 输出 3358
然后利用这个布尔型数组选出穿越了30的随机漫步(行),并调用argmax在轴1上获取穿越时间:
cross_times = (np.abs(walks[hits]) >= 30).argmax(1)
print(cross_times.mean()) # 获取平均值
尝试使用其他方式得到漫步数据。只需使用不通的随机数生成函数即可,如normal用于生成指定均值和标准差的正态分布数据
steps = np.random.normal(loc=0, scale=0.25, size=(nwalks,nsteps))
python 数据分析2的更多相关文章
-
[Python数据分析]新股破板买入,赚钱几率如何?
这是本人一直比较好奇的问题,网上没搜到,最近在看python数据分析,正好自己动手做一下试试.作者对于python是零基础,需要从头学起. 在写本文时,作者也没有完成这个小分析目标,边学边做吧. == ...
-
【Python数据分析】Python3多线程并发网络爬虫-以豆瓣图书Top250为例
基于上两篇文章的工作 [Python数据分析]Python3操作Excel-以豆瓣图书Top250为例 [Python数据分析]Python3操作Excel(二) 一些问题的解决与优化 已经正确地实现 ...
-
【Python数据分析】Python3操作Excel(二) 一些问题的解决与优化
继上一篇[Python数据分析]Python3操作Excel-以豆瓣图书Top250为例 对豆瓣图书Top250进行爬取以后,鉴于还有一些问题没有解决,所以进行了进一步的交流讨论,这期间得到了一只尼玛 ...
-
【搬砖】【Python数据分析】Pycharm中plot绘图不能显示出来
最近在看<Python数据分析>这本书,而自己写代码一直用的是Pycharm,在练习的时候就碰到了plot()绘图不能显示出来的问题.网上翻了一下找到知乎上一篇回答,试了一下好像不行,而且 ...
-
Python 数据分析(二 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识
Python 数据分析(二) 本实验将学习利用 Python 数据聚合与分组运算,时间序列,金融与经济数据应用等相关知识 第1节 groupby 技术 第2节 数据聚合 第3节 分组级运算和转换 第4 ...
-
Python数据分析(二): Numpy技巧 (1/4)
In [1]: import numpy numpy.__version__ Out[1]: '1.13.1' In [2]: import numpy as np
-
Python数据分析(二): Numpy技巧 (2/4)
numpy.pandas.matplotlib(+seaborn)是python数据分析/机器学习的基本工具. numpy的内容特别丰富,我这里只能介绍一下比较常见的方法和属性. 昨天晚上发了第一 ...
-
Python数据分析(二): Numpy技巧 (3/4)
numpy.pandas.matplotlib(+seaborn)是python数据分析/机器学习的基本工具. numpy的内容特别丰富,我这里只能介绍一下比较常见的方法和属性. 昨天晚上发了第一 ...
-
Python数据分析(二): Numpy技巧 (4/4)
numpy.pandas.matplotlib(+seaborn)是python数据分析/机器学习的基本工具. numpy的内容特别丰富,我这里只能介绍一下比较常见的方法和属性. 第一部分: ht ...
-
【读书笔记与思考】《python数据分析与挖掘实战》-张良均
[读书笔记与思考]<python数据分析与挖掘实战>-张良均 最近看一些机器学习相关书籍,主要是为了拓宽视野.在阅读这本书前最吸引我的地方是实战篇,我通读全书后给我印象最深的还是实战篇.基 ...
随机推荐
-
Javascript学习笔记:2种其他类型转换为数字Number类型的方式
①使用parseInt()/parseFloat()(在ECMAScript6中是Number.parseInt()/Number.parseFloat()) console.log(parseInt ...
-
N种内核注入DLL的思路及实现
内核注入,技术古老但很实用.现在部分RK趋向无进程,玩的是SYS+DLL,有的无文件,全部存在于内存中.可能有部分人会说:"都进内核了.什么不能干?".是啊,要是内核中可以做包括R ...
-
【poj2828】Buy Tickets
Description Railway tickets were difficult to buy around the Lunar New Year in China, so we must get ...
-
Linux设置固定IP
此处需整理 问题:在CentOS 7上,我想要将我其中一个网络接口从DHCP改为静态IP地址配置,如何才能永久为CentOS或RHEL 7上的网络接口分配静态IP地址? 如果你想要为CentOS 7中 ...
-
[每日一题] 11gOCP 1z0-052 :2013-09-27 bitmap index.................................................C37
转载请注明出处:http://blog.csdn.net/guoyjoe/article/details/12106027 正确答案C 这道题目是需要我们掌握位图索引知识点. 一.首先我们来看位图索引 ...
-
BZOJ 4016: [FJOI2014]最短路径树问题( 最短路 + 点分治 )
先跑出最短路的图, 然后对于每个点按照序号从小到大访问孩子, 就可以搞出符合题目的树了. 然后就是经典的点分治做法了. 时间复杂度O(M log N + N log N) -------------- ...
-
iOS 中隐藏UITableView最后一条分隔线
如何优雅的隐藏UITableView中最后一条分割线? 这个问题是很常见,却又不太容易解决的. 可能通常的做法都是隐藏UITableView的分割线,自定义一条. 最近在使用弹出菜单的时候,同样遇到了 ...
-
数据可视化——阿里云解决方案DataV
数据可视化——阿里云解决方案DataV https://help.aliyun.com/document_detail/53844.html?spm=a2c4g.11186623.6.579.37fd ...
-
jmeter学习笔记--线程组
jmeter组件:线程组 是什么? 进程:一个正在执行的程序对应一个进程 线程:进程中的执行线索(一个进程中有多个执行线索) 线程组:按照线程性质对线程进行分组 并发执行:多个线程同时进行 特点 ...
-
进度条QProgressBar
import sys from PyQt5.QtCore import Qt, QTimer from PyQt5.QtWidgets import QApplication, QWidget, QP ...