【numpy笔记_1】初识numpy
numpy和pandas是非常强大的科学计算和数据分析工具,在算法方面也有着广泛应用。
未来笔者会通过两个系列介绍numpy和pandas的基本使用,内容但求细致,算是对过往所学的总结。本篇将从numpy开始,认识下这个十分强大的科学计算模块。
安装numpy
windows:pip install numpy
其他系统,百度一下
什么是numpy?
如刚才所说,numpy是一个科学计算模块,numpy对象(称为array对象)中每个元素的数据类型都相同。使用numpy的计算十分高效,我们来看两个例子:
【例1】
定义一个包含一千万个数字的list,每个数字都加1。使用For循环和使用numpy 进行计算,来对比耗费的时间:
li = [i for i in range(10000000)]
ali = numpy.array(li)
st1 = time.time()
for index, item in enumerate(li): # enumereate()枚举方法
li[index] = item + 1
st2 = time.time()
ali = ali + 1 # 直接对每个元素 +1
st3 = time.time()
print(f'For循环:加一后的首个元素:{li[0]},末尾元素:{li[-1]},数组长度:{len(li)},耗时:{st2-st1}秒。')
print(f'numpy:加一后的首个元素:{ali[0]},末尾元素:{ali[-1]},数组长度:{len(ali)},耗时:{st3-st2}秒。')
# 运行结果:
For循环:加一后的首个元素:1,末尾元素:10000000,数组长度:10000000,耗时:1.5949997901916504秒。
numpy:加一后的首个元素:1,末尾元素:10000000,数组长度:10000000,耗时:0.019999980926513672秒。
【例2】
对上个例子中的list进行求和操作:
li = [i for i in range(10000000)]
ali = numpy.array(li)
st1 = time.time()
res1 = sum(li)
st2 = time.time()
res2 = ali.sum(dtype=numpy.int64) # 由于数组过大,需要指定array对象的数据类型,否则求和值超出元素的数据类型时会导致计算结果出错。
st3 = time.time()
print(f'普通求和结果:{res1},耗时:{st2-st1}秒。')
print(f'numpy求和结果:{res2},耗时:{st3-st2}秒。')
# 运行结果:
普通求和结果:49999995000000,耗时:0.24000000953674316秒。
numpy求和结果:49999995000000,耗时:0.00800013542175293秒。
可以看到,numpy处理数组的效率整体比普通的python运算快了近百倍。
但numpy的价值远不止于此。array对象基于固定的数字类型计算,其本质是由一个或多个数组组成的数字矩阵,既然是矩阵,说明array对象可以是一组或多组的数,这就是维度的概念。
创建一个numpy对象
我们通过numpy.array(object)方法创建一个array数组对象:
array_1d = numpy.array([1,3,5,7]) # array()方法创建
array_2d = numpy.array([[1,3,5,7],[2,4,6,8]])
array_3d = numpy.array([[[1,2,3],[4,5,6]],[[7,8,9],[10,11,12]]])
# 一维(1darray):shape = (4列)
[1 3 5 7]
# 二维(2darray):shape = (2行,4列)
[[1 3 5 7]
[2 4 6 8]]
# 三维(3darray):shape = (2维,2行,3列)
[[[ 1 2 3]
[ 4 5 6]]
[[ 7 8 9]
[10 11 12]]]
原则上,array对象的元素应是数字,但numpy同样支持创建str。
创建前python会检验元素类型,再给出能够包含所有元素的数据格式。
来看一个例子:
import numpy as np
li_1 = [1, 3]
li_2 = [1, True] # bool同时对应int类型的1, 0
li_3 = [False, True]
li_4 = [1, 3.279]
li_5 = [1, 'hello']
list_pool = [li_1, li_2, li_3, li_4, li_5]
for i in list_pool:
ali = np.array(i)
print(f'数据内容:{ali},类型:{ali.dtype}')
# 运行结果:
数据内容:[1 3] ,类型:int32
数据内容:[1 1] ,类型:int32
数据内容:[False True],类型:bool
数据内容:[1. 3.279],类型:float64
数据内容:['1' 'hello'],类型:
查看array对象的一些基本属性:
array_2d = numpy.array([[1,3,5,7],[2,4,6,8]])
print(array_2d)
print(f'array_2d对象的shape:{array_2d.shape}')
print(f'array_2d对象的dtype类型:{array_2d.dtype}')
print(f'array_2d对象的维度数:{array_2d.ndim}')
# 运行结果:
[[1 3 5 7]
[2 4 6 8]]
array_2d对象的shape:(2, 4)
array_2d对象的dtype类型:int32
array_2d对象的维度数:2
创建随机、全零、全1数组:
empty_array = numpy.empty((3,2), dtype=numpy.int32) # 创建并非空值,而是指定数据类型的随机数字
zeros_array = numpy.zeros((3,2), dtype=numpy.int32)
ones_array = numpy.ones((3,2), dtype=numpy.int32)
print(empty_array)
print('*'*20)
print(zeros_array)
print('*'*20)
print(ones_array)
# 运算结果:
[[-1201405844 2046]
[-1201393040 2046]
[ 5439567 69]]
********************
[[0 0]
[0 0]
[0 0]]
********************
[[1 1]
[1 1]
[1 1]]
知识补充:
上面【例2】中提到的dtype类型不对,数据运算时可能引发计算结果出错,是由于定义一个array对象时如果不指定数据类型,会根据元素值的大小(字节数)自动默认一种数据类型, 且求和的值遵守该数据类型。
如果某个array数组中存在的值相当多,和值的上限超出该数据类型的上限时,计算结果往往会出错。
ali1 = numpy.array([1,3,5,7])
ali2 = numpy.array([i for i in range(10000000)])
ali3 = numpy.array([0.3,1.00,0.0079])
print(f'ali1数据类型:{ali1.dtype}/nali2数据类型:{ali2.dtype}/nali3数据类型:{ali3.dtype}')
print(f'ali2未指定数据类型,直接求和的结果为:{ali2.sum()},和的数据类型:{type(ali2.sum())}')
# 运算结果:
ali1数据类型:int32
ali2数据类型:int32
ali3数据类型:float64
ali2未指定数据类型,直接求和的结果为:-2014260032,和的数据类型:
解决办法就是定义对象或进行求和操作时,定义一个更为合适的数字类型。
# 定义对象时指定数据类型
ali2 = numpy.array([i for i in range(1000000)], dtype=numpy.int64)
# 或,求和时制定数据类型
ali3 = numpy.array([i for i in range(1000000)])
res3 = ali3.sum(dtype=numpy.int64)
print(f'ali2求和的结果为:{ali2.sum()},和的数据类型:{ali2.sum().dtype}')
print(f'ali3求和的结果为:{res3},和的数据类型:{res3.dtype}')
# 运行结果:
ali2求和的结果为:499999500000,和的数据类型:int64
ali3求和的结果为:499999500000,和的数据类型:int64
对numpy的认识到这里就差不多了,未来会进一步学习numpy的常用操作。
共有 0 条评论