我正在尝试使用 numpy.genfromtxt 从文件中读取数据。 我将 names 参数设置为以逗号分隔的字符串列表,例如
names = ['a', '[b]', 'c']
但是,当返回数组时,dtype.names 值返回('a', 'b', 'c')
deletechars
参数未设置或强制None
。 我已经检查过,创建一个带有dtype的numpy.ndarray,该dtype具有带方括号的命名列,因此一定是genfromtxt正在删除方括号。 有没有办法关闭这个意外的功能?
请注意,如果 names
参数设置为 True
,也会发生此行为。 我已经在 numpy 版本 1.6.1 和 1.9.9 中对此进行了测试
我之前在 numpy 问题跟踪器和邮件列表中抱怨过这种字段名称重整行为。它也出现在之前关于SO的几个问题中。
事实上,默认情况下,即使您通过将字符串列表作为 names=
参数直接指定字段名称,np.genfromtxt
也会破坏字段名称:
import numpy as np
from io import BytesIO
s = '[5],name with spaces,(x-1)!n1,2,3n4,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'), ('x1n1', '<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'), ('x1n1', '<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')])
这可以是空字符串、列表、元组等。只要它的长度为零就没关系。
在字符串格式问题中(参数与下划线)我发现除了deletechars
参数之外还需要dtype=None
:
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)