NumPy基础知识(三)

NumPy基础知识(三)

  • 数据类型
  • 数组创建
  • 使用NumPy进行I / O
    • 使用导入数据 genfromtxt
      • 定义输入
      • 将行拆分为列
      • 跳过行并选择列
      • 选择数据类型
      • 设置名称
      • 调整转换
      • 快捷功能
  • 索引编制
  • 广播
  • 字节交换
  • 结构化数组
  • 编写自定义数组容器
  • 子数组ndarray

​​​​​​​使用导入数据 genfromtxt

NumPy提供了几种从表格数据创建数组的功能。我们在这里专注于genfromtxt功能。

简而言之,genfromtxt运行两个主循环。第一个循环以字符串序列转换文件的每一行。第二个循环将每个字符串转换为适当的数据类型。此机制比单循环慢,但具有更大的灵活性。特别genfromtxt是,在其他更快,更简单的功能(如loadtxt不能)时, 能够考虑丢失的数据。

注意

在给出示例时,我们将使用以下约定:

>>>

>>> import numpy as np
>>> from io import StringIO

定义输入

的唯一必选参数genfromtxt是数据源。它可以是字符串,字符串列表,生成器或带有read方法的打开的类似文件的对象,例如文件或 io.StringIO对象。如果提供单个字符串,则假定它是本地或远程文件的名称。如果提供了字符串列表或返回字符串的生成器,则将每个字符串视为文件中的一行。传递远程文件的URL后,该文件将自动下载到当前目录并打开。

公认的文件类型是文本文件和存档。当前,该功能可以识别gzipbz2bzip2)存档。存档的类型由文件的扩展名决定:如果文件名以结尾'.gz',则需要一个gzip存档;如果结尾为 'bz2'bzip2则假定为存档。

将行拆分为列

delimiter参数

定义文件并打开以供读取后,genfromtxt 将每条非空行拆分为一系列字符串。空行或注释行仅被跳过。该delimiter关键字用来定义分割应该如何发生。

通常,单个字符标记列之间的分隔。例如,逗号分隔文件(CSV)使用逗号(,)或分号(;)作为分隔符:

>>>

>>> data = u"1, 2, 3\n4, 5, 6"
>>> np.genfromtxt(StringIO(data), delimiter=",")
array([[ 1.,  2.,  3.],
       [ 4.,  5.,  6.]])

另一个常见的分隔符是"\t"制表符。但是,我们不仅限于单个字符,任何字符串都可以。默认情况下, genfromtxt假定delimiter=None为,表示该行沿空白(包括制表符)分隔,并且连续的空白被视为单个空白。

或者,我们可能正在处理一个固定宽度的文件,其中将列定义为给定数量的字符。在这种情况下,我们需要设置 delimiter为单个整数(如果所有列的大小都相同)或整数序列(如果列的大小可以不同):

>>>

>>> data = u"  1  2  3\n  4  5 67\n890123  4"
>>> np.genfromtxt(StringIO(data), delimiter=3)
array([[   1.,    2.,    3.],
       [   4.,    5.,   67.],
       [ 890.,  123.,    4.]])
>>> data = u"123456789\n   4  7 9\n   4567 9"
>>> np.genfromtxt(StringIO(data), delimiter=(4, 3, 2))
array([[ 1234.,   567.,    89.],
       [    4.,     7.,     9.],
       [    4.,   567.,     9.]])

autostrip参数

默认情况下,当将一行分解为一系列字符串时,不会删除各个条目的前导或尾随空格。通过将可选参数autostrip设置为值,可以覆盖此行为 True

>>>

>>> data = u"1, abc , 2\n 3, xxx, 4"
>>> # Without autostrip
>>> np.genfromtxt(StringIO(data), delimiter=",", dtype="|U5")
array([['1', ' abc ', ' 2'],
       ['3', ' xxx', ' 4']], dtype='
>>> # With autostrip
>>> np.genfromtxt(StringIO(data), delimiter=",", dtype="|U5", autostrip=True)
array([['1', 'abc', '2'],
       ['3', 'xxx', '4']], dtype='

comments参数

可选参数comments用于定义标记注释开始的字符串。默认情况下, genfromtxt假设comments='#'。注释标记可以出现在行中的任何位置。注释标记后的任何字符都将被忽略:

>>>

>>> data = u"""#
... # Skip me !
... # Skip me too !
... 1, 2
... 3, 4
... 5, 6 #This is the third line of the data
... 7, 8
... # And here comes the last line
... 9, 0
... """
>>> np.genfromtxt(StringIO(data), comments="#", delimiter=",")
array([[1., 2.],
       [3., 4.],
       [5., 6.],
       [7., 8.],
       [9., 0.]])

在1.7.0版本的新功能:comments设置为None,没有行被视为注释。

注意

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

跳过行并选择列

usecols参数

在某些情况下,我们对数据的所有列都不感兴趣,但仅对其中的一些感兴趣。我们可以选择使用usecols参数导入的列 。此参数接受与要导入的列的索引相对应的单个整数或整数序列。请记住,按照惯例,第一列的索引为0。负整数的行为与常规Python负索引相同。

例如,如果我们只想导入第一列和最后一列,则可以使用:usecols=(0, -1)

>>>

>>> data = u"1 2 3\n4 5 6"
>>> np.genfromtxt(StringIO(data), usecols=(0, -1))
array([[ 1.,  3.],
       [ 4.,  6.]])

如果这些列具有名称,我们还可以通过将其名称作为usecols参数以字符串序列或逗号分隔的字符串作为参数来选择要导入的列:

>>>

>>> data = u"1 2 3\n4 5 6"
>>> np.genfromtxt(StringIO(data),
...               names="a, b, c", usecols=("a", "c"))
array([(1.0, 3.0), (4.0, 6.0)],
      dtype=[('a', '
>>> np.genfromtxt(StringIO(data),
...               names="a, b, c", usecols=("a, c"))
    array([(1.0, 3.0), (4.0, 6.0)],
          dtype=[('a', '

选择数据类型

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

  • 单一类型,例如dtype=float。输出将是具有给定dtype的2D,除非使用names参数将名称与每个列相关联(请参见下文)。请注意,这dtype=float是的默认设置 genfromtxt

  • 类型序列,例如。dtype=(int, float, float)

  • 逗号分隔的字符串,例如dtype="i4,f8,|U3"

  • 有两个键'names'和的字典'formats'

  • 一组元组,如 。(name, type)dtype=[('A', int), ('B', float)]

  • 现有numpy.dtype对象。

  • 特殊价值None。在这种情况下,列的类型将由数据本身确定(请参见下文)。

在除第一种情况以外的所有情况下,输出都是具有结构化dtype的一维数组。此dtype的字段与序列中的项目一样多。字段名称使用names关键字定义。

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

dtype=None提供该选项是为了方便。但是,它比显式设置dtype慢得多。

设置名称

names参数

处理表格数据时,一种自然的方法是为每个列分配一个名称。如前所述,第一种可能性是使用显式结构化dtype:

>>>

>>> data = StringIO("1 2 3\n 4 5 6")
>>> np.genfromtxt(data, dtype=[(_, int) for _ in "abc"])
array([(1, 2, 3), (4, 5, 6)],
      dtype=[('a', '

另一个更简单的可能性是将names关键字与字符串序列或逗号分隔的字符串一起使用:

>>>

>>> data = StringIO("1 2 3\n 4 5 6")
>>> np.genfromtxt(data, names="A, B, C")
array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)],
      dtype=[('A', '

在上面的示例中,我们使用了默认情况下的事实dtype=float。通过提供一系列名称,我们将输出强制为结构化dtype。

有时我们可能需要根据数据本身定义列名称。在这种情况下,我们必须使用names值为的关键字 Trueskip_header即使从第一行中删除了注释,也将从第一行中读取名称 :

>>>

>>> data = StringIO("So it goes\n#a b c\n1 2 3\n 4 5 6")
>>> np.genfromtxt(data, skip_header=1, names=True)
array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)],
      dtype=[('a', '

默认值namesNone。如果我们给关键字赋予其他任何值,则新名称将覆盖我们可能已经用dtype定义的字段名称:

>>>

>>> data = StringIO("1 2 3\n 4 5 6")
>>> ndtype=[('a',int), ('b', float), ('c', int)]
>>> names = ["A", "B", "C"]
>>> np.genfromtxt(data, names=names, dtype=ndtype)
array([(1, 2.0, 3), (4, 5.0, 6)],
      dtype=[('A', '

defaultfmt参数

如果names=None只需要结构化dtype,则使用标准NumPy默认值定义"f%i"名称,产生类似的名称f0, f1依此类推:

>>>

>>> data = StringIO("1 2 3\n 4 5 6")
>>> np.genfromtxt(data, dtype=(int, float, int))
array([(1, 2.0, 3), (4, 5.0, 6)],
      dtype=[('f0', '

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

>>>

>>> data = StringIO("1 2 3\n 4 5 6")
>>> np.genfromtxt(data, dtype=(int, float, int), names="a")
array([(1, 2.0, 3), (4, 5.0, 6)],
      dtype=[('a', '

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

>>>

>>> data = StringIO("1 2 3\n 4 5 6")
>>> np.genfromtxt(data, dtype=(int, float, int), defaultfmt="var_%02i")
array([(1, 2.0, 3), (4, 5.0, 6)],
      dtype=[('var_00', '

注意

我们需要记住,defaultfmt仅当需要某些名称但未定义某些名称时才使用该名称。

验证名称

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

deletechars

给出一个字符串,其中包含必须从名称中删除的所有字符。默认情况下,无效字符为 。~!@#$%^&*()-=+~\|]}[{';: /?.>,<

excludelist

给人的名字排除,如列表returnfile, print...如果输入的名称之一是这份名单的一部分,一个下划线字符('_')将追加到它。

case_sensitive

名称是否区分大小写(case_sensitive=True),转换为大写(case_sensitive=False或 case_sensitive='upper')还是小写(case_sensitive='lower')。

调整转换

converters参数

通常,定义dtype足以定义必须如何转换字符串序列。但是,有时可能需要一些其他控制。例如,我们可能要确保将格式中的日期 YYYY/MM/DD转换为datetime对象,或者将类似的字符串xx%正确转换为0到1之间的浮点数。在这种情况下,我们应该使用converters 参数定义转换函数。

该参数的值通常是一个字典,其中以列索引或列名作为键,而转换函数作为值。这些转换函数可以是实际函数,也可以是lambda函数。无论如何,它们都应仅接受字符串作为输入,并仅输出所需类型的单个元素。

在下面的示例中,第二列从表示百分比的字符串转换为0到1之间的浮点数

>>>

>>> convertfunc = lambda x: float(x.strip(b"%"))/100.
>>> data = u"1, 2.3%, 45.\n6, 78.9%, 0"
>>> names = ("i", "p", "n")
>>> # General case .....
>>> np.genfromtxt(StringIO(data), delimiter=",", names=names)
array([(1., nan, 45.), (6., nan, 0.)],
      dtype=[('i', '

我们需要记住默认情况下dtype=float。因此,第二列应该有浮点数。但是,不能将字符串 和转换为浮点数,而最终得到了 。现在让我们使用一个转换器:' 2.3%'' 78.9%'np.nan

>>>

>>> # Converted case ...
>>> np.genfromtxt(StringIO(data), delimiter=",", names=names,
...               converters={1: convertfunc})
array([(1.0, 0.023, 45.0), (6.0, 0.78900000000000003, 0.0)],
      dtype=[('i', '

通过将第二列的名称("p")用作键而不是其索引(1),可以获得相同的结果:

>>>

>>> # Using a name for the converter ...
>>> np.genfromtxt(StringIO(data), delimiter=",", names=names,
...               converters={"p": convertfunc})
array([(1.0, 0.023, 45.0), (6.0, 0.78900000000000003, 0.0)],
      dtype=[('i', '

转换器还可以用于为缺少的条目提供默认值。在下面的示例中,转换器convert将剥离后的字符串转换为相应的float,如果字符串为空,则转换为-999。我们需要显式地从空格中删除字符串,因为默认情况下不这样做:

>>>

>>> data = u"1, , 3\n 4, 5, 6"
>>> convert = lambda x: float(x.strip() or -999)
>>> np.genfromtxt(StringIO(data), delimiter=",",
...               converters={1: convert})
array([[   1., -999.,    3.],
       [   4.,    5.,    6.]])

使用缺失值和填充值

我们尝试导入的数据集中可能缺少一些条目。在前面的示例中,我们使用了转换器将空字符串转换为浮点型。但是,用户定义的转换器可能很快变得难以管理。

genfromtxt函数提供了另外两种补充机制:missing_values参数用于识别丢失的数据,第二个参数filling_values用来处理这些丢失的数据。

missing_values

默认情况下,任何空字符串都标记为丢失。我们还可以考虑使用更复杂的字符串,例如"N/A""???"表示丢失或无效的数据。该missing_values参数接受三种值:

字符串或逗号分隔的字符串

该字符串将用作所有列缺少数据的标记

字符串序列

在这种情况下,每个项目都按顺序关联到一列。

一本字典

字典的值是字符串或字符串序列。相应的键可以是列索引(整数)或列名称(字符串)。此外,特殊键None可用于定义适用于所有列的默认值。

filling_values

我们知道如何识别丢失的数据,但是我们仍然需要为这些丢失的条目提供一个值。默认情况下,此值是根据下表根据预期dtype确定的:

预期类型

默认

bool

False

int

-1

float

np.nan

complex

np.nan+0j

string

'???'

使用filling_values可选参数,我们可以更好地控制缺失值的转换 。像一样 missing_values,此参数接受不同类型的值:

单一价值

这将是所有列的默认值

一系列值

每个条目将是对应列的默认条目

一本字典

每个键可以是列索引或列名,并且对应的值应该是单个对象。我们可以使用特殊键None为所有列定义默认值。

在下面的示例中,我们假设缺少的值"N/A"在第一列和"???"第三列中用标记。如果这些缺失值出现在第一和第二列中,我们希望将它们转换为0,如果它们出现在最后一列中则转换为-999:

>>>

>>> data = u"N/A, 2, 3\n4, ,???"
>>> kwargs = dict(delimiter=",",
...               dtype=int,
...               names="a,b,c",
...               missing_values={0:"N/A", 'b':" ", 2:"???"},
...               filling_values={0:0, 'b':0, 2:-999})
>>> np.genfromtxt(StringIO(data), **kwargs)
array([(0, 2, 3), (4, 0, -999)],
      dtype=[('a', '

usemask

我们可能还想通过构造一个布尔掩码来跟踪丢失数据的发生,True其中包含数据丢失的条目以及False其他条目。为此,我们只需将可选参数设置usemaskTrue(默认值为False)。然后,输出数组将为MaskedArray

快捷功能

此外genfromtxt,该numpy.lib.io模块还提供了一些衍生自的便捷功能 genfromtxt。这些功能与原始功能相同,但是具有不同的默认值。

recfromtxt

返回一个标准numpy.recarray(if usemask=False)或一个 MaskedRecords数组(if usemaske=True)。默认dtype为dtype=None,这意味着将自动确定每列的类型。

recfromcsv

喜欢recfromtxt,但具有默认值delimiter=","

你可能感兴趣的:(技术学习,python,numpy)