【问题标题】:Create a numpy array of mixed column types from data using genfromtxt使用 genfromtxt 从数据创建一个混合列类型的 numpy 数组
【发布时间】:2016-08-14 08:58:48
【问题描述】:

我的问题是如何从具有 int 类型列和字符串的 csv 文件创建一个 numpy (np) 数组。我发现 np.genfromtxt 被记录为这个 [1,2] 的选择函数。我正在使用 python 3.5.1 和 numpy 1.11.0。但是,我发现的最新 numpy 文档适用于 1.10.0 [3]。当我进一步得到一个 numpy 错误时,这可能很有趣。

让我从我所拥有的开始

import numpy as np
from io import BytesIO

# Define the input
input = "1,3,Hello\n2,4,World"

# Create a structured np.array from input by reading from BytesIO.
output = np.genfromtxt(BytesIO(input.encode()),
                       delimiter=',',
                       dtype=None)

# output.dtype.names -> ('f0', 'f1', 'f2')

这里,列 f0 和 f1 是 int 类型,f2 是一个字节数组。因此

output['f2'] == 'Hello'  # -> False

为假,因为类型不同。正确的比较必须写成

output['f2'] == b'Hello' # -> [True, False]

我更喜欢与字符串而不是字节数组进行比较。因此,我希望 f2 是 str 类型。解决方案应该是明确说明每列的类型。根据 [1],这应该可以通过设置 genfromtxt 参数来实现

dtype=(int, int, str)

这样最小的例子现在变成了

import numpy as np
from io import BytesIO

# Define the input
input = "1,3,Hello\n2,4,World"

# Create a structured np.array from input by reading from BytesIO.
output = np.genfromtxt(BytesIO(input.encode()),
                       delimiter=',',
                       dtype=(int, int, str))

但是,这会导致TypeError: data type not understood。也许,numpy 版本 1.10.0 和 1.11.0 之间发生了一些变化。无论如何,我无法让它工作。

因此,我尝试了第二种方法,使用 genfromtxt 的转换器参数。使用此参数,值可以通过函数进行转换。现在的例子是

import numpy as np
from io import BytesIO

# Define the input
input = "1,3,Hello\n2,4,World"

# Create a structured np.array from input by reading from BytesIO.
output = np.genfromtxt(BytesIO(input.encode()),
                       delimiter=',',
                       dtype=None,
                       converters={2: lambda x: str(x, encoding='utf-8')})

通过这样做,f2 的实际类型为 <U,我将其解释为 little-endian 编码中的 utf-8,但 f2 的每一行仅存在一个空字符串 ''

那么,我怎样才能读取给定的数据,使得 f0 和 f1 是 int 而 f2 是 str?

[1]http://docs.scipy.org/doc/numpy-1.10.1/user/basics.io.genfromtxt.html

[2]http://docs.scipy.org/doc/numpy-1.10.0/reference/generated/numpy.genfromtxt.html

[3]http://docs.scipy.org/doc/numpy/

【问题讨论】:

  • 这和TeX有关系吗?
  • 不,你应该在stackoverflow上问它
  • 哦,对不起。我使用了错误的登录名。
  • py3 中,您的测试输入可能只是txt=b'1,2,....'.splitlines(),一个字节串列表。

标签: python-3.x numpy


【解决方案1】:

Unicode 字符串的dtype 代码是U。对于使用固定大小的块,需要长度。在这种情况下U5 就足够了:

>>> np.genfromtxt(BytesIO(input.encode()),
                      delimiter=',',
                      dtype=(int, int, 'U5'))
array([(1, 3, 'Hello'), (2, 4, 'World')], 
      dtype=[('f0', '<i8'), ('f1', '<i8'), ('f2', '<U5')])

【讨论】:

  • 感谢您的回答。如果我将块大小设置得太宽,比如 U20,则相应列的类型为
  • @ReedWood 是的,类型必须具有固定大小。每行都有一个固定大小,称为步幅,可以通过数组属性stride 访问。如果你想检查底层字节数据,那么属性data 可以像bytearray(a.data) 一样使用a 作为数组对象。 a.nbytes 给出字节大小。上面的数组,但带有U20 的两行使用了 192 个字节。步长为 96 个字节,每个整数 8 个字节,Unicode 字符串 80 个字节,每个字符使用 4 个字节。
  • Unicode 字符串的长度是隐式的。对于字符串表示,以零作为数值的尾随代码点将被忽略。只要字符串末尾有一个非零字符,代码为零的嵌入字符就可以了。
  • 感谢您的澄清。对我来说很有意义。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-17
  • 2020-08-04
  • 2014-05-10
  • 2013-01-19
  • 2020-01-05
  • 1970-01-01
  • 2014-09-10
相关资源
最近更新 更多