Numpy.genfromtxt删除dtype.names中的方括号

时间:2016-02-05 22:28:47

标签: python numpy genfromtxt

我正在尝试使用numpy.genfromtxt从文件中读取数据。我将names参数设置为以逗号分隔的字符串列表,例如

names = ['a', '[b]', 'c']

但是,返回数组时,dtype.names值将返回('a', 'b', 'c')

deletechars参数未设置或强制为None。我已经检查过创建一个带有带有方括号的命名列的dtype的numpy.ndarray会保留方括号,所以必须是genfromtxt删除方括号。有没有办法关闭这个意想不到的功能?

注意,如果names参数设置为True,也会发生此行为。我已经在numpy版本1.6.1和1.9.9

中测试了这个

2 个答案:

答案 0 :(得分:2)

我之前在numpy issue tracker和邮件列表上抱怨过这个字段名称错位行为。它也出现在several previous questions的SO上。

实际上,默认情况下np.genfromtxt会破坏字段名称,即使您通过将字符串列表作为names=参数传递直接指定它们:

import numpy as np
from io import BytesIO

s = '[5],name with spaces,(x-1)!\n1,2,3\n4,5,6'

x = np.genfromtxt(BytesIO(s), delimiter=',', names=True)
print(repr(x))
# array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)], 
#       dtype=[('5', '<f4'), ('name_with_spaces', '<f4'), ('x1\n1', '<f4')])

names = s.split(',')[:3]
x = np.genfromtxt(BytesIO(s), delimiter=',', skip_header=1, names=names)
print(repr(x))
# array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)], 
#       dtype=[('5', '<f4'), ('name_with_spaces', '<f4'), ('x1\n1', '<f4')])

尽管包含非字母数字字符的字段名称完全合法,但仍会发生这种情况:

x2 = np.empty(2, dtype=dtype)
x2[:] = [(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)]
print(repr(x2))
# array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)], 
#       dtype=[('[5]', '<f4'), ('name with spaces', '<f4'), ('(x-1)!\n1', '<f4')])

这种行为的逻辑逃脱了我。

正如您所见,将None作为deletechars=参数传递不足以防止这种情况发生,因为此参数在内部初始化为numpy._iotools.NameValidator内的一组默认字符

但是,你可以传递一个空序列:

x = np.genfromtxt(BytesIO(s), delimiter=',', names=True, deletechars='')
print(repr(x))
# array([(1.0, 2.0, 3.0), (4.0, 5.0, 6.0)], 
#       dtype=[('[5]', '<f8'), ('name_with_spaces', '<f8'), ('(x-1)!', '<f8')])

这可能是一个空字符串,列表,元组等。只要它的长度为零就没关系。

答案 1 :(得分:2)

String formatting issue (parantheses vs underline) 我发现除dtype=None参数外还需要deletechars

https://stackoverflow.com/a/32540939/901925

In [168]: np.genfromtxt([b'1,2,3'],names=['a','[b]','xcx'],delimiter=',',deletechars='',dtype=None)
Out[168]: 
array((1, 2, 3), 
      dtype=[('a', '<i4'), ('[b]', '<i4'), ('xcx', '<i4')])

使用默认的dtype(浮点数)时,会使用deletechars,但名称会通过第二个验证程序easy_dtype,但不会获得此参数。

In [170]: np.genfromtxt([b'1,2,3'],names=['a','[b]','xcx'],delimiter=',',deletechars='x')
Out[170]: 
array((1.0, 2.0, 3.0), 
      dtype=[('a', '<f8'), ('b', '<f8'), ('c', '<f8')])

https://github.com/numpy/numpy/pull/4649

加载后可以更改字段名称:

In [205]: data=np.genfromtxt([b'1 2 3 txt'],names=['a','b','c','d'],dtype=[int,float,int,'S4'])

In [206]: data.dtype.names
Out[206]: ('a', 'b', 'c', 'd')

In [207]: data.dtype.names=['a','[b]','*c*','d']

In [208]: data
Out[208]: 
array((1, 2.0, 3, 'txt'), 
      dtype=[('a', '<i4'), ('[b]', '<f8'), ('*c*', '<i4'), ('d', 'S4')])

这适用于从文件本身获取的名称:

In [212]: data=np.genfromtxt([b'a [b] *c* d','1 2 3 txt'],dtype=[int,float,int,'S4'],names=True)