不理解NumPy loadtxt中转换器的行为

5 投票
2 回答
20315 浏览
提问于 2025-04-16 19:56

我正在尝试使用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 个回答

4

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]])

不过如果这样做的话,你就不能按列来指定格式了。

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版本才能解决这个问题)。

撰写回答