0

我在尝试将 txt 文件加载到结构化数组中时遇到问题。

这是一个显示问题的简单示例。

这工作正常:

import numpy as np
from StringIO import StringIO 

in1 = StringIO("123 456 789\n231 543 876")
a = np.loadtxt(in1, dtype=[('x', "int"), ('y', "int"), ('z', "int")])

####output
array([(123, 456, 789), (231, 543, 876)], 
      dtype=[('x', '<i8'), ('y', '<i8'), ('z', '<i8')])

但是,当其中一个字段包含小数时,尝试将其转换为 int 时出现错误:

in2 = StringIO("123 456 789\n231 543.0 876")
a = np.loadtxt(in2, dtype=[('x', "int"), ('y', "int"), ('z', "int")])

####error
ValueError: invalid literal for long() with base 10: '543.0'

我希望 python 能够将“543.0”之类的数字转换为 543 而不会引发错误。

如果它只是一个数字,我可以使用类似的东西

int(float("543.0"))

但是我可以结合 numpy 的 loadtxt 来做到这一点吗?

实际上,我要读取的文件大约为 2Gigs,并且具有长度为 37 的复杂 dtype,其中包含浮点数、字符串和整数的混合。

我试过 numpy.genfromtxt,它似乎适用于较小的文件,但它在 2gig 文件上占用了太多内存。

我考虑过的另一个选择是用 sed 截断所有以“.0”结尾的数字,这会起作用,但更像是一种 hack,而不是真正的解决方案。

有没有更蟒蛇的方法?

已回答(感谢Zhenya)...

dtypeTmp = np.dtype([(d[0], "<f8") if d[1] == "<i8" else d for d in dtype1.descr])
events = np.loadtxt("file.txt", dtype=dtypeTmp)
events.astype(dtype1)
4

2 回答 2

2

对于应该是整数的字段,您可以使用一个转换器int(float(fieldval))。下面显示了一种loadtxt converters基于 dtype 以编程方式创建参数的方法:

In [77]: in3 = StringIO("123.0 456 789 0.95\n231 543.0 876 0.87")

In [78]: dt = dtype([('x', "int"), ('y', "int"), ('z', "int"), ('r', "float")])

In [79]: converters = dict((k, lambda s: int(float(s))) for k in range(len(dt)) if np.issubdtype(dt[k], np.integer))

In [80]: converters
Out[80]: 
{0: <function __main__.<lambda>>,
 1: <function __main__.<lambda>>,
 2: <function __main__.<lambda>>}

In [81]: a = np.loadtxt(in3, dtype=dt, converters=converters)

In [82]: a
Out[82]: 
array([(123, 456, 789, 0.95), (231, 543, 876, 0.87)], 
      dtype=[('x', '<i8'), ('y', '<i8'), ('z', '<i8'), ('r', '<f8')])

loadtxt即使这样,在 2 gig 文件上使用时,您仍可能会遇到性能或内存问题。你调查过pandas吗?它的 csv 阅读器比 numpy 中的阅读器快得多。

于 2013-07-12T20:02:35.323 回答
1

无需手动编辑任何内容:

>>> in2 = StringIO("123 456 789\n231 543.0 876")
>>> dt_temp = np.dtype([('x', "int"), ('y', "float"), ('z', "int")])
>>> a = np.loadtxt(in2, dtype=dt_temp)
>>> 
>>> dt = np.dtype([('x', "int"), ('y', "int"), ('z', "int")])
>>> b = a.astype(dt)
>>> b
array([(123, 456, 789), (231, 543, 876)], 
      dtype=[('x', '<i8'), ('y', '<i8'), ('z', '<i8')])
于 2013-07-12T18:47:31.457 回答