编程手养成计划 Day7、8

NumPy基础(二)

一、创建数组

(一)将Python array_like对象转换为Numpy数组

个人理解为将python中的列表类型list转化为ndarry类型

import numpy as np
x = np.array([2,3,1,0])

(二)Numpy原生数组的创建

1. 数组生成函数汇总
函数名描述
array将输入数据转换为ndarray,如不显式指明数据类型,将自行判断;默认复制所有的输入数据
asarray将输入转换为ndarray,但如果输入已经是ndarray则不再复制
arangePython内建函数range的数组版,返回一个数组
ones根据给定形状和数据类型生成全1数组
ones_like根据所给的数组生成一个形状一样的全1数组
zeros根据给定形状和数据类型生成全0数组
zeros_like根据所给的数组生成一个形状一样的全0数组
empty根据给定形状生成一个没有初始化的空数组
empty_like根据所给的数组生成一个形状一样但没有初始化的数组
full根据给定形状和数据类型生成指定数值的数组
full_like根据所给的数组生成一个形状一样但内容是指定数值的数组
linspace创建具有指定数量元素的数组,并在指定的开始值和结束值之间平均间隔。
indices创建一组可以表示每个维度变化的数组。
eye,identity生成一个 N × N N\times N N×N特征矩阵(对角线1,其余0)
2. zeros()

我们可以使用zeros()函数创建一个全为0的数组,数组的默认dtypefloat64

import numpy as np
x = np.zeros((2, 3), dtype=np.int_)
3. ones()

同样的,我们可以使用ones()创建一个全为1的数组,用法与zeros()相同。

import numpy as np
x = np.ones((2, 3), dtype=np.int_)
4. empty()

我们也可以使用empty()创建一个没有初始化数值的数组。

import numpy as np
x = np.empty((2, 4))
5. nidm、shape

我们可以通过检查nidmshape属性检查建立的数组。

>>> import numpy as np
>>> x = np.zeros((2, 4, 3))
>>> x.nidm	# 返回维数,这里为三维数组
3
>>> x.shape
(2, 4, 3)	# 返回数组的具体结构
6. arange()

与python中range()类似,可以使用arange()创建具有有规律递增值的数组。

>>> import numpy as np
>>> np.arange(10)		# 输出从0到9的数组(相当于省略初始值)
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])

>>> np.arange(2, 10)		# 输出从2到9的数组
array([2, 3, 4, 5, 6, 7, 8, 9])

>>> np.arange(2, 10, 3)		# 输出从2到9的数组,步长为3
array([2, 5, 8])

>>>np.arange(2, 4, dtype = np.int_)	# 设置数据类型(无小数默认为int32,小数默认为float64)
7. linspace()

我们可以使用linspace()来创建一个包含始末数字的数组,其中数组的长度可以指定。默认数据类型为float64

>>> import numpy as np
>>> np.linspace(2, 4, 3)
array([2., 3., 4.])
8. indices()

indices()将创建一组数组(堆积为一个更高维的数组),每个维度一个,每个维度表示该维度中的变化。

>>> import numpy as np
>>> np.indices((3,3))
array([[[0, 0, 0],	# 这一边从上至下递加
        [1, 1, 1],
        [2, 2, 2]],
	   
       [[0, 1, 2],	# 这一边从左至右递加
        [0, 1, 2],
        [0, 1, 2]]])

(三)从硬盘中读取数组

详见:NumPy中文网:从磁盘读取数组

二、NumPy与输入输出

(一)NumPy内建二进制格式

np.savenp.load是高效存储硬盘数据的两大工具函数。数组在默认情况下是以未压缩的格式进行存储的,后缀名是.npy

1. save()

我们可以通过np.save保存数组,如果文件存放路径中没写,会自动补上.npy

import numpy as np
x = np.ones((2, 4))
np.save('1', x)
2. load()

硬盘上的数组可以通过np.load进行载入

import numpy as np
x = np.load('1.npy')
print(x)
3. savez()

我们可以使用savez并将数组作为参数传递给该函数,用于在压缩文件(.npz)中保存多个数组

import numpy as np
x = np.ones((2, 4))
y = np.zeros((2, 4))
np.savez('1', a=x, b=y)		# 通过键值对(字典)的形式创建文件

当我们载入一个.npz文件时,会获得一个字典。

import numpy as np
arch = np.load("1.npz")		# 读取文件".npz"
print(arch['a'])		# 读取键'a'的值
4. savez_compressed

如果你的数据已经压缩好了,你可能会想要使用np.savez_compressed将数据存入已经压缩好的文件。

import numpy as np
z = np.zeros((5, 4))
np.savez_compressed('1.npz', c=z)	# 创建键值对c-->z

(二)使用genfromtxt导入数据

首先,我们新建 1.txt 用于储存数据

1,2,3,4,5
6,7,8,9,10
1. 定义输入

genfromtxt的唯一强制参数是数据的来源。它可以是一个字符串,一串字符串或一个生成器(file, str, pathlib.Path, list of str, 或者generator)。如果提供了单个字符串,则假定它是本地或远程文件的名称,或者带有read方法的开放文件类对象。如果提供了字符串列表或生成器返回字符串,则每个字符串在文件中被视为一行。当传递远程文件的URL时,该文件将自动下载到当前目录并打开。
同时,genfromtxt还可以自动识别文件是否是压缩类型,目前支持两种压缩类型:gzipbz2

2. 将行拆分为列
(1)delimiter参数

一旦文件被定义并打开进行读取,genfromtxt会将每个非空行分割为一串字符串。 空的或注释的行只是略过。 delimiter关键字用于定义拆分应该如何进行。

  • 根据字符来分割:
>>> import numpy as np
>>> np.genfromtxt("1.txt", delimiter=",")
array([[ 1.,  2.,  3.,  4.,  5.],
       [ 6.,  7.,  8.,  9., 10.]])
  • 根据空格来分割:

为方便展示,我们重写 1.txt 中的数据

1 2 3 4 5
6 7  8   9      10

在书写时,我们故意将后几位的空格拉长。
默认情况下,genfromtxt假定delimiter=None,这意味着该行沿着空白区域(包括制表符)分割,并且连续的空白区域被视为单个空白区域。

>>> import numpy as np
>>> np.genfromtxt("1.txt")	# 读取"1.txt"中的数据
array([[ 1.,  2.,  3.,  4.,  5.],
       [ 6.,  7.,  8.,  9., 10.]])
  • 根据字符长度来分割:

此时,1.txt 中的数据如下

1234
5678

在这种情况下,我们需要将delimiter设置为单个整数(如果所有列的大小相同)或整数序列(如果列的大小可能不同):

>>> import numpy as np
>>> np.genfromtxt("1.txt", delimiter=1)		# delimiter为单个整数
array([[1., 2., 3., 4.],
       [5., 6., 7., 8.]])
>>> np.genfromtxt("1.txt", delimiter=(2, 1))	# delimiter为整数序列
array([[12.,  3.],
       [56.,  7.]])
(2)autostrip参数

当配置autostrip=True,python会自动删除分割后字符的前后空格。

1.txt 文件如下:

1,  2,3,   4
5  ,  6  , 7,  8

功能实现如下:

>>> import numpy as np
>>> np.genfromtxt("1.txt", delimiter=',', dtype=str)
array([['1', '  2', '3', '   4'],
       ['5  ', '  6  ', ' 7', '  8']], dtype='<U5')
>>> np.genfromtxt("1.txt", delimiter=',', dtype=str, autostrip=True)
array([['1', '2', '3', '4'],
       ['5', '6', '7', '8']], dtype='<U1')

我们发现在输出中,所以开头和结尾的空格被删除。

其中:dtype='<U1'中:

  • <表示字节顺序,小端(最小有效字节存储在最小地址中)
  • U表示Unicode,数据类型
  • 1表示元素位长,数据大小
(3)comments参数

可选参数comments用于定义标记注释开始的字符串。默认情况下,genfromtxt假定comments='#'

我们首先重新编辑 1.txt 中的内容:

1,2,3//123
//456
4,5,6

代码实现:

>>> import numpy as np
>>> np.genfromtxt("1.txt", delimiter=',', comments='//')	# 以'//'为注释标志
array([[1., 2., 3.],
       [4., 5., 6.]])

我们发现,这里的注释规则与python中#一致。

注意
这种行为有一个明显的例外:如果可选参数names=True,则会检查第一条注释行的名称。

3. 跳过直线并选择列
(1)skip_header和skip_footer参数

skip_headerskip_footer参数用来跳过开头/末尾的某些行,我们可以通过控制参数的取值控制开头/结尾忽略的行数,默认情况下skip_headerskip_footer均等于0。
首先我们编辑一下 1.txt 中的数据

1,2,3
4,5,6
7,8,9

代码实现:

>>> import numpy as np
>>> np.genfromtxt("1.txt", delimiter=',', skip_header=1)	# 忽略第一行
array([[4., 5., 6.],
       [7., 8., 9.]])
>>> np.genfromtxt("1.txt", delimiter=',', skip_footer=2)	# 忽略后两行
array([1., 2., 3.])
(2)usecols参数

我们可以通过usecols参数来指定读取哪些列。该参数接受与要导入的列的索引相对应的单个整数或整数序列。按照惯例,第一列的索引为0。负整数的行为与常规Python负向索引相同。
本例中, 1.txt 文件同上,下面是代码实现。

>>> import numpy as np
>>> np.genfromtxt("1.txt", delimiter=',', usecols=1)	# 取第二列
array([2., 5., 8.])
>>> np.genfromtxt("1.txt", delimiter=',', usecols=(1, 2))	# 取第二至三列
array([[2., 3.],
       [5., 6.],
       [8., 9.]])

我们还可以通过列名指定需要的哪些行:

下面我们将用三种方式指定第一、三行,代码如下

>>> import numpy as np
>>> np.genfromtxt("1.txt", delimiter=',', 
				  names='a, b, c', usecols=('a', 'c'))	# 通过字符串序列指定
array([(1., 3.), (4., 6.), (7., 9.)], dtype=[('a', '<f8'), ('c', '<f8')])

>>> np.genfromtxt("1.txt", delimiter=',', 
				  names='a, b, c', usecols='a, c')	# 通过逗号分隔字符串指定
array([(1., 3.), (4., 6.), (7., 9.)], dtype=[('a', '<f8'), ('c', '<f8')])

>>> np.genfromtxt("1.txt", delimiter=',', 
				  names='a, b, c', usecols=('a', 2))	# 混合方式指定
array([(1., 3.), (4., 6.), (7., 9.)], dtype=[('a', '<f8'), ('c', '<f8')])
4. 选择数据的类型

控制我们从文件中读取的字符串序列如何转换为其他类型的主要方法是设置dtype参数。这个参数的可接受值是:

  • 单一类型,如dtype=float。除非使用names参数将名称与每个列关联(见下文),否则输出将是给定dtype的2D格式。请注意,dtype=floatgenfromtxt的默认值。
  • 一系列类型,如dtype=(int, float, float)
  • 逗号分隔的字符串,例如dtype="i4,f8,|S3"
  • 一个包含两个键'names''formats'的字典。
  • 一个元组序列(name, type), 像dtype=[('A', int), ('B', float)]
  • 现有的numpy.dtype对象。
  • 特殊值None。在这种情况下,列的类型将根据数据本身确定(见下文)。

在所有情况下,除了第一种情况,输出将是一个带有结构化dtype的一维数组。这个dtype与序列中的项目一样多。字段名称由names关键字定义。

dtype=None时,每列的类型由其数据迭代确定。我们首先检查一个字符串是否可以转换为布尔值(也就是说,如果字符串在小写字母中匹配truefalse);然后是否可以将其转换为整数,然后转换为浮点数,然后转换为复数并最终转换为字符串。通过修改StringConverter类的默认映射器可以更改此行为。

5. 设置名称
(1)结构化dtype

在上面我们曾遇到过这样的数据array([(1., 3.), (4., 6.), (7., 9.)], dtype=[('a', '<f8'), ('c', '<f8')]),不难发现他的dtype信息中包含了列名,我们可以通过设置来定义。
首先,我们的 1.txt 中的数据如下:

1 2 3
4 5 6
7 8 9

下面是python代码

>>> import numpy as np
>>>np.genfromtxt("1.txt", dtype=[(_, int) for _ in "abc"])
array([(1, 2, 3), (4, 5, 6), (7, 8, 9)],
      dtype=[('a', '<i4'), ('b', '<i4'), ('c', '<i4')])
(2)names参数

使用names参数可以让我们更简单的命名

>>> import numpy as np
>>> np.genfromtxt("1.txt", names='a, b, c')
array([(1., 2., 3.), (4., 5., 6.), (7., 8., 9.)],
      dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])

在上面的例子中,我们使用了默认情况下dtype=float的事实。通过给出一个名称序列,我们强制输出到一个结构化的dtype

names还支持从数据中读取列名:
我们重新配置一下 1.txt 文件

a b c
1 2 3
4 5 6
7 8 9

下面让我们设置names=True:

>>> import numpy as np
>>> np.genfromtxt("1.txt", names=True)
array([(1., 2., 3.), (4., 5., 6.), (7., 8., 9.)],
      dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])

通过上面的代码,我们成功的设置了列名。同时我们发现,即使第一行被注释掉,仍然可以正常读取出列名。即将 1.txt 第一行设置为#a b c

names的默认值为None。如果我们给关键字赋予任何其他值,新名称将覆盖我们可能用dtype定义的字段名称:
1.txt:

1 2 3
4 5 6
7 8 9

Python代码:

>>> import numpy as np
>>> ndtype=[('a',int), ('b', float), ('c', int)]
>>> names = ["A", "B", "C"]
>>> np.genfromtxt("1.txt", names=names, dtype=ndtype)
array([(1, 2., 3), (4, 5., 6), (7, 8., 9)],
      dtype=[('A', '<i4'), ('B', '<f8'), ('C', '<i4')])

换言之,当我们同时在dtypenames中设置列名,names的优先级更高。

(3)defaultfmt参数

如果 names=None 的时候,只是预计会有一个结构化的dtype,它的名称将使用标准的NumPy默认值 "f%i"来定义,会产生例如f0f1等名称:

>>> import numpy as np
>>> np.genfromtxt('1.txt', dtype=(int, float, int))
array([(1, 2., 3), (4, 5., 6), (7, 8., 9)],
      dtype=[('f0', '<i4'), ('f1', '<f8'), ('f2', '<i4')])

同样,如果我们没有提供足够的名称来匹配dtype的长度,缺少的名称将使用此默认模板进行定义:

>>> import numpy as np
>>> np.genfromtxt('1.txt', dtype=(int, float, int), names='a')
array([(1, 2., 3), (4, 5., 6), (7, 8., 9)],
      dtype=[('a', '<i4'), ('f0', '<f8'), ('f1', '<i4')])

我们可以使用defaultfmt参数覆盖此默认值,该参数采用任何格式字符串:

>>> import numpy as np
>>> np.genfromtxt('1.txt', dtype=(int, float, int), defaultfmt="var_%02i")
array([(1, 2., 3), (4, 5., 6), (7, 8., 9)],
      dtype=[('var_00', '<i4'), ('var_01', '<f8'), ('var_02', '<i4')])

注意!
我们需要记住,仅当预期一些名称但未定义时才使用defaultfmt

(4)验证名称

具有结构化dtype的NumPy数组也可以被视为recarray,其中可以像访问属性一样访问字段。因此,我们可能需要确保字段名称不包含任何空格或无效字符,或者它不对应于标准属性的名称(如sizeshape),这会混淆解释者。genfromtxt接受三个可选参数,这些参数可以更好地控制名称:

  • deletechars - 给出一个字符串,将所有必须从名称中删除的字符组合在一起。默认情况下,无效字符是~!@#$%^&*()-=+~\|]}[{';: /?.>,<
  • excludelist - 给出要排除的名称列表,如returnfileprint …如果其中一个输入名称是该列表的一部分,则会附加一个下划线字符('_')。
  • case_sensitive - 是否区分大小写(case_sensitive=True),转换为大写(case_sensitive=Falsecase_sensitive='upper')或小写(case_sensitive='lower')。
6. 快捷方式函数

除了 genfromtxt 之外,numpy.lib.io模块还提供了几个从 genfromtxt 派生的方便函数。这些函数的工作方式与原始函数相同,但它们具有不同的默认值。

  • recfromtxt - 返回标准 numpy.recarray(如果 usemask=False)或 MaskedRecords数组(如果 usemaske=True)。默认dtype是 dtype=None ,意味着将自动确定每列的类型。
  • recfromcsv - 类似 recfromtxt,但有默认值 delimiter=","
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值