我在尝试将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文件中太多的内存。
我考虑过的另一个选择是截断所有以“.0”结尾的数字,使用sed,这将起作用,但更多的是黑客而不是真正的解决方案。
有更多的pythonic方法吗?
已回答(感谢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)
答案 0 :(得分:2)
对于应该是整数的字段,您可以使用执行int(float(fieldval))
的转换器。以下显示了一种基于dtype以编程方式创建loadtxt
converters
参数的方法:
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')])
即使这样,在2 gig文件上使用loadtxt
时,您仍可能遇到性能或内存问题。你看过pandas
了吗?它的csv阅读器比numpy的阅读器要快得多。
答案 1 :(得分: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')])