【问题标题】:dtype for integer, three floatsdtype 整数,三个浮点数
【发布时间】:2015-10-29 05:27:29
【问题描述】:

我有一个文本文件,除其他数据外,它还包含以下形式的数据

215
1 0.0 0.0 0.0
[...]
9 -0.4330127018930699 0.2499999999985268 1.0
10 -0.1366025403783193 -0.03660254037890862 1.0
11 -0.2499999999985268 -0.4330127018930699 1.0
12 0.03660254037890862 -0.1366025403783193 1.0
13 0.4330127018930699 -0.2499999999985268 1.0
14 0.1366025403783193 0.03660254037890862 1.0
15 0.2499999999985268 0.4330127018930699 1.0
[...]
215 1.0 1.0 1.0
[...]  # some more data, other format

即,

  • 一个整数,指定即将到来的数据行数,
  • N 行,一个整数后跟三个浮点数,
  • 更多数据,格式不同。

我想将这些数据转换成一个 numpy 数组。由于我可以最好地使用生成器访问文件,numpy.fromiter() 就派上用场了。不过,我未能正确指定数据类型。这个

with open(filename) as f:
    line = islice(f, 1).next()
    num_nodes = int(line)
    points = numpy.fromiter(
        islice(f, num_nodes),
        dtype=[('idx', int, 1), ('vals', float, 3)],
        count=num_nodes
        )

工作。有什么提示吗?

【问题讨论】:

  • 我建议loadtxtgenfromtxt。使用dtype=None,他们将为您推断出 int v float。或尝试i,f,f,f dtype。您的 dtype 也可能有效。
  • 我很难使用需要文件句柄的方法,因为该文件包含许多其他格式不同的数据。这就是我使用生成器 (islice) 的原因。
  • genfromtxt 接受任何可以一次输入一行的内容。为了测试,我经常使用字符串列表。生成器应该可以正常工作。

标签: python numpy file-io string-formatting


【解决方案1】:

这个脚本:

import numpy as np

txt = b"""7
9 -0.4330127018930699 0.2499999999985268 1.0
10 -0.1366025403783193 -0.03660254037890862 1.0
11 -0.2499999999985268 -0.4330127018930699 1.0
12 0.03660254037890862 -0.1366025403783193 1.0
13 0.4330127018930699 -0.2499999999985268 1.0
14 0.1366025403783193 0.03660254037890862 1.0
15 0.2499999999985268 0.4330127018930699 1.0
[...]  # some more data, other format
"""
dt = np.dtype([('idx', int, 1), ('vals', float, 3)])
#dt = np.dtype('i,f,f,f')
print(dt)

def gentxt(txt, dt):
    f = txt.splitlines()
    line = f[0]
    num_nodes = int(line)
    aslice = slice(1,num_nodes+1)
    # print(f[aslice])
    points = np.genfromtxt(
        f[aslice],
        dtype=dt)
    return points

M = gentxt(txt,dt)
print(repr(M))

生产

1304:~/mypy$ python3 stack33406545.py 
[('idx', '<i4'), ('vals', '<f8', (3,))]
array([(9, [-0.4330127018930699, 0.2499999999985268, 1.0]),
       (10, [-0.1366025403783193, -0.03660254037890862, 1.0]),
       (11, [-0.2499999999985268, -0.4330127018930699, 1.0]),
       (12, [0.03660254037890862, -0.1366025403783193, 1.0]),
       (13, [0.4330127018930699, -0.2499999999985268, 1.0]),
       (14, [0.1366025403783193, 0.03660254037890862, 1.0]),
       (15, [0.2499999999985268, 0.4330127018930699, 1.0])], 
      dtype=[('idx', '<i4'), ('vals', '<f8', (3,))])

我使用了对文本行列表的简单切片。我试着像你一样使用islice,但我认为不值得我花时间把它做好。核心是使用可生成所需文本行的可交互对象。无论是列表、文件行范围还是生成器的输出,都没有关系。


fromiter 对其接受的内容很挑剔。它必须产生一个一维数组;

返回单个字符串(可转换为简单 dtype)的列表或可迭代对象工作:

In [233]: np.fromiter(['1', '2', '3', '4'],dtype=int)
Out[233]: array([1, 2, 3, 4])

但列表列表 (2d) 没有:

In [234]: np.fromiter([['1', '2'],['3', '4']],dtype=int)
....
ValueError: setting an array element with a sequence.

对于复杂的 dtype,我必须给它元组:

In [236]: np.fromiter([('1', '2'),('3', '4')],dtype=np.dtype('i,i'))
Out[236]: 
array([(1, 2), (3, 4)], dtype=[('f0', '<i4'), ('f1', '<i4')])

带有多个数字的字符串或字符串元组不起作用,['1 2','3 4'][('1 2',),('3 4',)]genfromtxt 可以更好地处理带有行和列的文本(类似 csv)。

【讨论】:

    猜你喜欢
    • 2021-01-16
    • 2019-11-18
    • 2016-11-23
    • 2011-01-04
    • 1970-01-01
    • 1970-01-01
    • 2017-08-19
    • 2021-09-27
    • 2017-07-26
    相关资源
    最近更新 更多