Numpy基础知识

数据类型

1.数据类型之间的转换

  • 5种基本类型:bool、int、uint、float、复数。
  • int32代表32位整型
  • 在创建时指定类型的两种方式,直接类型 or 类型字符。
    astype 改变数组的类型
    直接a.dtype获取数组类型
>>> import numpy as np
>>> a=np.arange(12,dtype=float)
>>> a
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11.])
>>> a=np.arange(12,dtype='i')
>>> a
array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11], dtype=int32)
>>> a.dtype
dtype('int32')
>>> a.astype('float')
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9., 10., 11.])

2.数组标量

  • NumPy通常将数组元素作为数组标量返回(带有关联dtype的标量

3.溢出错误

  • 当值需要比数据类型中的可用内存更多的内存时,NumPy数值类型的固定大小可能会导致溢出错误
#100的8次方超出32位存储空间
>>> np.power(100, 8, dtype=np.int64)
10000000000000000
>>> np.power(100, 8, dtype=np.int32)
1874919424
  • Python中的int大小是灵活的,不会溢出。
  • Numpy提供numpy.iinfo和numpy.finfo验证NumPy整数和浮点值的最小值或最大值
>>> np.finfo(float)
finfo(resolution=1e-15, min=-1.7976931348623157e+308, max=1.7976931348623157e+308, dtype=float64)
>>> np.iinfo(int)
iinfo(min=-2147483648, max=2147483647, dtype=int32)
>>> np.iinfo(np.int64)
iinfo(min=-9223372036854775808, max=9223372036854775807, dtype=int64)

如果64位整数仍然太小,则结果可能会转换为浮点数。浮点数提供了更大但不精确的可能值范围。
np.power(100,100,dtype=np.float64)

扩展精度

  • 为了有效地进行内存的校准,np.longdouble通常以零位进行填充,即96或者128位, 哪个更有效率取决于硬件和开发环境;通常在32位系统上它们被填充到96位,而在64位系统上它们通常被填充到128位。
  • 尽管它们的名称是这样叫的, 但是np.float96和np.float128只提供与np.longdouble一样的精度, 即大多数x86机器上的80位和标准Windows版本中的64位。

创建数组

1. 从其他Python结构(例如,列表,元组)转换

>>> a=np.array((1,2,3,4))
>>> a
array([1, 2, 3, 4])
>>> b=np.array([5,6,2])
>>> b
array([5, 6, 2])
>>> c = np.array([[1,2],(3,4)])
>>> c
array([[1, 2],
       [3, 4]])

2. numpy原生数组的创建(例如,arange、ones、zeros等)

np.zeros((n,m)) 填充0
np.ones((n,m))  填充1
#n,m代表数组的形状
np.linspace(n,m,p)
n为开始,p为结束,m为个数

3. 从磁盘读取数组,无论是标准格式还是自定义格式

  • 使用 numpy.fromfile() 函数和 .tofile() 方法直接读取和写入numpy数组

4. 通过使用字符串或缓冲区从原始字节创建数组

5. 使用特殊库函数(例如,random)

Numpy输入与输出

使用genfromtxt导入数据

  • genfromtxt执行两个主要的循环。第一个循环以字符串序列转换文件的每一行。第二个循环将每个字符串转换为适当的数据类型

定义输入

  • 唯一强制参数是数据的来源

将行拆分为列

delimiter为None的时候,按制表符分割

>>> from io import BytesIO
>>> data = b"1,2,3\n4,5,6"
>>> np.genfromtxt(BytesIO(data),delimiter=",")
array([[1., 2., 3.],
       [4., 5., 6.]])
>>> data=b"     1       2       2"
>>> np.genfromtxt(BytesIO(data),delimiter=None)
array([1., 2., 2.])
  • delimiter为整数或数组时,可以规定输出的数组中每个列的宽度
>>> data=b"12345\n  3 4\n56  7"
>>> np.genfromtxt(BytesIO(data),delimiter=(3,2))
array([[123.,  45.],
       [  3.,   4.],
       [ 56.,   7.]])
#数组第一列宽为3,第二列宽为2
  • autostrip参数,为True时可消除每个元素的前导空白和尾随空白
  • comments可用于定义标记注释开始的字符串。默认情况下为#
>>> data=b"""#
... #comment
... #comment
... 1.2
... 3.4
... 5.6
... #commeng
... """
>>> np.genfromtxt(BytesIO(data),delimiter='.',comments="#")
array([[1., 2.],
       [3., 4.],
       [5., 6.]])
  • skip_header(n)和skip_footer(n)分别代表从头部和尾部跳过n个行
>>> data = "\n".join(str(i) for i in range(10))
>>> np.genfromtxt(BytesIO(data),)
array([ 0.,  1.,  2.,  3.,  4.,  5.,  6.,  7.,  8.,  9.])
>>> np.genfromtxt(BytesIO(data),
...               skip_header=3, skip_footer=5)
array([ 3.,  4.])
  • usecols参数,截取部分列
>>> data = "1 2 3\n4 5 6"
>>> np.genfromtxt(BytesIO(data), usecols=(0, -1))
array([[ 1.,  3.],
       [ 4.,  6.]])
#获取第一列和最后一列

设置名称

  • names参数,给列指定名称,可以用对应的列名来用usecols选出列。
>>> data=b"1 2 3\n4 5 6"
>>> np.genfromtxt(BytesIO(data),names="a,b,c",usecols=("a","c"))
array([(1., 3.), (4., 6.)], dtype=[('a', '<f8'), ('c', '<f8')])
>>> np.genfromtxt(BytesIO(data),usecols=(0,-1))
array([[1., 3.],
       [4., 6.]])
  • 从数据本身定义列名,使用names关键字的值为True。这些名字将从第一行(在skip_header之后)被读取。
  • 在函数中names参数具有最高优先级,优于其他方式定义的名称
  • defaultfmt参数
    当names为None,默认为f0,f1等等。或names不够时,也是如此。
    defaultfmt覆盖默认值
    例:defaultfmt=“var_%i”
  • deletechars 删除列表
  • excludelist 排除列表
  • case_sensitive 大小写

选择数据的类型

接受一个dtype参数设置数据类型

  • 一个包含两个键'names'和'formats'的字典。
  • 现有的numpy.dtype对象。
  • 特殊值None。在这种情况下,列的类型将根据数据本身确定(见下文)。
  • 以下四点见代码
>>> np.genfromtxt(BytesIO(data),usecols=(0,-1),dtype=int)
array([[1, 3],
       [4, 6]])
>>> np.genfromtxt(BytesIO(data),usecols=(0,-1),dtype='i4')
array([[1, 3],
       [4, 6]])
>>> np.genfromtxt(BytesIO(data),names="a,b,c",dtype=[('a',int),('b',float)])
array([(1, 2.), (4, 5.)], dtype=[('a', '<i4'), ('b', '<f8')])
>>> np.genfromtxt(BytesIO(data),names="a,b,c",dtype=(int,float,float))
array([(1, 2., 3.), (4, 5., 6.)],
      dtype=[('a', '<i4'), ('b', '<f8'), ('c', '<f8')])

除直接的dtype=int之外,其他的返回的都是一个带有结构化dtype的一维数组。

调整转换

  • converters定义转换函数。
    converters参数必须是一个字典。
>>> data=b"1,2,3\n4,5,6\n"
>>> names="a,b,c"
>>> np.genfromtxt(BytesIO(data))
array([nan, nan])
>>> np.genfromtxt(BytesIO(data),delimiter=',')
array([[1., 2., 3.],
       [4., 5., 6.]])
>>> np.genfromtxt(BytesIO(data),delimiter=',',names=names)
array([(1., 2., 3.), (4., 5., 6.)],
      dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])
>>> def func(x):
...     return '0'
...
>>> 
np.genfromtxt(BytesIO(data),delimiter=',',dtype=int,names=names,converters={'b':func})
array([(1, 0, 3), (4, 0, 6)],
      dtype=[('a', '<i4'), ('b', '<i4'), ('c', '<i4')])
  • missing_values 和filling_values分别代表丢失值和为丢失值设定的值
  • usemask,布尔掩码,True为缺失

索引

切片索引

>>> y = np.arange(35).reshape(5,7)
>>> y
array([[ 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, 32, 33, 34]])
>>> y[1:5:2,::3]
array([[ 7, 10, 13],
       [21, 24, 27]])

索引数组

>>> x = np.arange(10,1,-1)
>>> x
array([10,  9,  8,  7,  6,  5,  4,  3,  2])
>>> x[np.array([3, 3, 1, 8])]
array([7, 7, 9, 2])

索引多维数组

>>> y[np.array([0,2,4]), np.array([0,1,2])]
array([ 0, 15, 30])

在这种情况下,如果索引数组具有匹配的形状,并且索引数组的每个维度都有一个索引数组,则结果数组具有与索引数组相同的形状

>>> y[np.array([0,2,4]), np.array([0,1])]
<type 'exceptions.ValueError'>: shape mismatch: objects cannot be
broadcast to a single shape

如果索引数组的形状不同,则尝试将它们广播为相同的形状。如果它们无法广播到相同的形状,则会引发异常

>>> y[np.array([0,2,4]), 1]
array([ 1, 15, 29])

广播机制允许索引数组与其他索引的标量组合

  • 可以仅使用索引数组对数组进行部分索引
>>> y[np.array([0,2,4])]
array([[ 0,  1,  2,  3,  4,  5,  6],
       [14, 15, 16, 17, 18, 19, 20],
       [28, 29, 30, 31, 32, 33, 34]])

布尔或掩码索引数组

  • 布尔数组做索引返回的是一维数组
>>> b = y>20
>>> y[b]
array([21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34])
>>> b[:,5]
array([False, False, False,  True,  True])
>>> y[b[:,5]]
array([[21, 22, 23, 24, 25, 26, 27],
       [28, 29, 30, 31, 32, 33, 34]])
#此时的b[:,5]相当于【3,4】
  • 布尔索引要和被索引数组的形状完全相同才能索引到每一个元素。
    如果布尔索引少一个维度,那么对数组进行索引时的最小单位就上升一个维度。
>>> x
array([[[ 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]]])
>>> a=np.array([True,True,False,True,False])
>>> a
array([ True,  True, False,  True, False])
>>> b=np.array([[a,a,a],[a,a,a]])
>>> b
array([[[ True,  True, False,  True, False],
        [ True,  True, False,  True, False],
        [ True,  True, False,  True, False]],

       [[ True,  True, False,  True, False],
        [ True,  True, False,  True, False],
        [ True,  True, False,  True, False]]])
>>> x[b]
array([ 0,  1,  3,  5,  6,  8, 10, 11, 13, 15, 16, 18, 20, 21, 23, 25, 26,
       28])

在程序中使用索引

  • slice 切片
  • Ellipsis 省略号
>>> indices = (1,1,1,1)
>>> z[indices]
40
>>> indices = (1,1,1,slice(0,2)) # same as [1,1,1,0:2]
>>> z[indices]
array([39, 40])
>>> indices = (1, Ellipsis, 1) # same as [1,...,1]
>>> z[indices]
array([[28, 31, 34],
       [37, 40, 43],
       [46, 49, 52]])

广播

术语广播(Broadcasting)描述了 numpy 如何在算术运算期间处理具有不同形状的数组

  • 当一个数组和一个标量值在一个操作中组合时,会发生最简单的广播
>>> a = np.array([1.0, 2.0, 3.0])
>>> b = 2.0
>>> a * b
array([ 2.,  4.,  6.])

一般广播规则

在两个数组上运行时,NumPy会逐元素地比较它们的形状。它从尾随尺寸开始,并向前发展。两个尺寸兼容时
1.他们是平等的,或者
2.其中一个是1

  • 平等的意味着
    1.有相同的形状
    2.最外围的元素个数相同
    例:a和b最外围都是3个
>>> import numpy as np
>>> a=np.array([[1,2,3],[3,4,5],[5,6,7]])
>>> b=np.array([1,2,3]),
>>> a*b
array([[ 1,  4,  9],
       [ 3,  8, 15],
       [ 5, 12, 21]])
  • 各种情况
A      (2d array):  5 x 4
B      (1d array):      1
Result (2d array):  5 x 4

A      (2d array):  5 x 4
B      (1d array):      4
Result (2d array):  5 x 4

A      (3d array):  15 x 3 x 5
B      (3d array):  15 x 1 x 5
Result (3d array):  15 x 3 x 5

A      (3d array):  15 x 3 x 5
B      (2d array):       3 x 5
Result (3d array):  15 x 3 x 5

A      (3d array):  15 x 3 x 5
B      (2d array):       3 x 1
Result (3d array):  15 x 3 x 5
>>> x = np.arange(4)
>>> xx = x.reshape(4,1)
>>> y = np.ones(5)
>>> z = np.ones((3,4))
>>> x.shape
(4,)
>>> y.shape
(5,)
>>> x + y
ValueError: operands could not be broadcast together with shapes (4,) (5,)
>>> xx.shape
(4, 1)
>>> y.shape
(5,)
>>> (xx + y).shape
(4, 5)
>>> xx + y
array([[ 1.,  1.,  1.,  1.,  1.],
       [ 2.,  2.,  2.,  2.,  2.],
       [ 3.,  3.,  3.,  3.,  3.],
       [ 4.,  4.,  4.,  4.,  4.]])
>>> x.shape
(4,)
>>> z.shape
(3, 4)
>>> (x + z).shape
(3, 4)
>>> x + z
array([[ 1.,  2.,  3.,  4.],
       [ 1.,  2.,  3.,  4.],
       [ 1.,  2.,  3.,  4.]])
>>> a = np.array([0.0, 10.0, 20.0, 30.0])
>>> b = np.array([1.0, 2.0, 3.0])
>>> a[:, np.newaxis] + b
array([[  1.,   2.,   3.],
       [ 11.,  12.,  13.],
       [ 21.,  22.,  23.],
       [ 31.,  32.,  33.]])

字节交换

字节排序和ndarrays

ndarray是一个为内存中的数据提供python数组接口的对象
  • 关于一些2字节整数与4字节整数之间的转换之类的。
  • 更改数组dtype中的字节顺序信息,以便将基础数据解释为不同的字节顺序。这是作用 arr.newbyteorder()
  • 更改基础数据的字节顺序,保留dtype解释。这是做什么的 arr.byteswap()
  • dtype参数很重要

结构化数组

  • 结构化数组,ndarray。包含dtype,一个一维数组,元素是元组。
>>> import numpy as np
>>> x = np.array([('李栋良',22,84),('Daenerys',22,55)],
...              dtype=[('name','U10'),('age','i4'),('weight','f4')]
...
...
... )
>>> x
array([('李栋良', 22, 84.), ('Daenerys', 22, 55.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])
>>> x[name]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'name' is not defined
>>> x['name']
array(['李栋良', 'Daenerys'], dtype='<U10')
>>> x['age']=23
>>> x
array([('李栋良', 23, 84.), ('Daenerys', 23, 55.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])
>>> x['weight'][1]=54
>>> x
array([('李栋良', 23, 84.), ('Daenerys', 23, 54.)],
      dtype=[('name', '<U10'), ('age', '<i4'), ('weight', '<f4')])

结构化数据类型创建

  • 元组列表的形式,shape是可选的
    np.dtype([('x', 'f4'), ('y', np.float32), ('z', 'f4', (2, 2))])
  • 逗号分隔,字段名称被赋予默认名称 f0、f1等
    np.dtype('i8, f4, S3')
    dtype([('f0', '<i8'), ('f1', '<f4'), ('f2', 'S3')])
  • 字段参数组字典
    字典有两个必需键 “names” 和 “format”,以及四个可选键 “offsets”、“itemsize”、“Aligned” 和 “title”。
>>> np.dtype({'names':['A','B'],'formats':['i4','f4']})
dtype([('A', '<i4'), ('B', '<f4')])

可以通过names使用相同长度的字符串序列分配属性来修改字段名称。

dtype对象还具有类似字典的属性,fields其键是字段名称, 其值是包含每个字段的dtype和字节偏移量的元组。

>>> d.fields
mappingproxy({'x': (dtype('int64'), 0), 'y': (dtype('float32'), 8)})
  • 偏移量指的是内存中的偏移,可以认为指定,也可以自动偏移和对齐。
    默认情况下(align=False),numpy将字段打包在一起,使得每个字段从前一个字段结束的字节偏移开始,并且字段在内存中是连续的
>>> d=np.dtype('u1,i8,f4,u2,u1,i4')
>>> d.fields
mappingproxy({'f0': (dtype('uint8'), 0), 'f1': (dtype('int64'), 1), 'f2': (dtype('float32'), 9), 'f3': (dtype('uint16'), 13), 'f4': (dtype('uint8'), 15), 'f5': (dtype('int32'), 16)})
>>> [d.fields[name][1] for name in d.names]
[0, 1, 9, 13, 15, 16]
  • 如果align=True设置了,numpy将以与许多C编译器填充C结构相同的方式填充结构
>>> d=np.dtype('u1,i8,f4,u2,u1,i4',align=True)
>>> [d.fields[name][1] for name in d.names]
[0, 8, 16, 20, 22, 24]

索引和分配给结构化数组

  • 使用元组赋值
  • 使用标量赋值,会将标量分配给所有字段
>>> x=np.array(2,dtype='i4,u1')
>>> x
array((2, 2), dtype=[('f0', '<i4'), ('f1', 'u1')])
  • 来自其他结构化数组的赋值是可以的。但是具有不同数量的字段的结构化数组不能彼此分配

索引

  • 使用名称索引和修改
  • 访问的字段是子数组,则子数组的维度将附加到结果的形状
>>> x = np.zeros((2, 2), dtype=[('a', np.int32), ('b', np.float64, (3, 3))])
>>> x
array([[(0, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]),
        (0, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])],
       [(0, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]]),
        (0, [[0., 0., 0.], [0., 0., 0.], [0., 0., 0.]])]],
      dtype=[('a', '<i4'), ('b', '<f8', (3, 3))])
>>> x['a'].shape
(2, 2)
>>> x['b'].shape
(2, 2, 3, 3)
  • 结构化数组中的名称可看作列名
>>> a=np.zeros(3)
>>> a
array([0., 0., 0.])
>>> a=np.zeros(3, dtype=[('a', 'i4'), ('b', 'i4'), ('c', 'f4')])
>>> a
array([(0, 0, 0.), (0, 0, 0.), (0, 0, 0.)],
      dtype=[('a', '<i4'), ('b', '<i4'), ('c', '<f4')])
>>> a[['a','c']]
array([(0, 0.), (0, 0.), (0, 0.)],
      dtype={'names':['a','c'], 'formats':['<i4','<f4'], 'offsets':[0,8], 'itemsize':12})
  • 使用整数进行索引获得结构化标量,获得的结构化标量也像视图一样,进行修改会修改原数组

结构比较

>>> a=np.ones(2,dtype='i4,u1')
>>> a
array([(1, 1), (1, 1)], dtype=[('f0', '<i4'), ('f1', 'u1')])
>>> b=np.ones(2,dtype='i4,u1')
>>> a==b
array([ True,  True])

记录数组

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

推荐阅读更多精彩内容