不理解NumPy loadtxt中转换器的行为
我正在尝试使用numpy.loadtxt从一个文本文件中读取数据,并且使用了converters参数。我的数据中有整数和字符串混合的列。代码如下:
a, b, c, d, e = np.loadtxt(infile, delimiter = ',', usecols=(0, 2, 5, 8, 9), skiprows = 1,
unpack = True, converters = dict(zip((0, 2, 5, 8, 9), (int, float, float, int, int))))
数据读取和解包都没问题,但所有的变量(a、b、c、d和e)最后都变成了浮点数。我是不是在converters的语法上搞错了?
编辑尝试回答
我按照@joris的建议,尝试使用dtype = (int,float,float,int,int),代码如下:
a,b,c,d,e = np.loadtxt(infile,delimiter = ',', usecols=(0,2,5,8,9), skiprows = 1, unpack = True, dtype = (int,float,float,int,int))
但是我遇到了以下错误:
41 skiprows = 1,
42 unpack = True,
---> 43 dtype = (int,float,float,int,int))
44
45
/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/numpy/lib/npyio.pyc in loadtxt(fname, dtype, comments, delimiter, converters, skiprows, usecols, unpack)
665 try:
666 # Make sure we're dealing with a proper dtype
--> 667 dtype = np.dtype(dtype)
668 defconv = _getconv(dtype)
669
TypeError: data type not understood
WARNING: Failure executing file: <forward_NDMMF.py>
我使用的是NumPy版本1.5.1。
2 个回答
loadtxt
的说明文档提到,converters
应该包含一些函数,这些函数会专门返回浮点数:
converters : 字典,可选
这是一个字典,用来把列号映射到一个函数,这个函数会把该列的数据转换成浮点数。例如,如果第0列是日期字符串,你可以这样写:converters = {0: datestr2num}。
converters
也可以用来为缺失的数据提供默认值,比如:converters = {3: lambda s: float(s or 0)}。默认值是None。
如果你想要整数的话,你需要使用dtype
这个关键字把浮点数转换成整数。
>>> numpy.loadtxt('th.txt', delimiter=',', usecols=(0, 2, 3), converters=dict(zip((0, 2, 3), (float, float, float))), dtype=([('i1', '<i4'), ('i2', '<f4'), ('i3', '<i4')]))
array([(1, 3.2000000476837158, 4), (1, 3.2000000476837158, 4),
(1, 3.2000000476837158, 4), (1, 3.2000000476837158, 4),
(1, 3.2000000476837158, 4), (1, 3.2000000476837158, 4),
(1, 3.2000000476837158, 4), (1, 3.2000000476837158, 4),
(1, 3.2000000476837158, 4)],
dtype=[('i1', '<i4'), ('f1', '<f4'), ('i2', '<i4')])
当然,在这种情况下其实并不需要converters
-- 它主要是用来把一些任意的字符串值,比如'True'
,转换成数字。此外,如果你想要一个简单的二维数组,而不是记录数组,那就不要传递记录格式:
>>> numpy.loadtxt('th.txt', delimiter=',', usecols=(0, 2, 3), dtype=int)
array([[1, 3, 4],
[1, 3, 4],
[1, 3, 4],
[1, 3, 4],
[1, 3, 4],
[1, 3, 4],
[1, 3, 4],
[1, 3, 4],
[1, 3, 4]])
不过如果这样做的话,你就不能按列来指定格式了。
在指定不同列的类型时,你可以使用参数 dtype
,而不是 converters
:
dtype=(int,float,float,int,int)
编辑:
显然,这种 dtype
的指定方式在 loadtxt
中似乎不太好用,但在 genfromtxt
中可以正常工作。有人知道为什么 loadtxt
不行吗?还是说这是 genfromtxt
的额外功能?
如果你想用 loadtxt
,可以用包含元组的结构化 dtype
来指定,比如 [('f0', int), ('f1', float)]
,而不是 (int, float)
。
不过还有另一个问题。当使用这种结构化的 dtype
和结构化数组(不同列有不同类型)时,unpack
似乎不太好用。至少我尝试的简单例子是这样的。但这可能是一个已经解决的bug:http://projects.scipy.org/numpy/ticket/1458(不过你得升级到1.6版本才能解决这个问题)。