【问题标题】:Numpy.genfromtxt deleting square brackets in dtype.namesNumpy.genfromtxt 删除 dtype.names 中的方括号
【发布时间】:2016-05-16 01:11:27
【问题描述】:

我正在尝试使用 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 中对此进行了测试

【问题讨论】:

    标签: python numpy genfromtxt


    【解决方案1】:

    我之前曾在 numpy issue tracker 和邮件列表中抱怨过此字段名称修改行为。它也在 SO 上的several previous questions 中出现。

    事实上,默认情况下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')])
    

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

    【讨论】:

    • 谢谢,ali_m。我在错误跟踪器here 中看到了这个解决方案。 @unutbu,正在考虑事后更正,但空参数要容易得多。将测试,然后接受答案。
    • 这些字符在结构化数组 dtype 中可能没问题,但不能作为 recarray 的属性名称。我在argparse 中看到了同样的紧张——你给用户足够的绳子让他们自己上吊吗?
    • @hpaulj 不——它们对于recarrays也是合法的(当然你不能使用.attribute风格的语法来访问它们)。它们是否应该合法是另一个问题,但我的观点是np.genfromtxt 不应该随意乱用合法的字段名称。
    • loadtxt 使用 dtype=np.dtype([('a','i'),('[b]','f'),('c','f')]) 没有变化。
    • 我刚刚也注意到了这一点——在最近的版本中可能已经改变了。不过,我的其他反对意见仍然存在 :-)
    【解决方案2】:

    String formatting issue (parantheses vs underline) 我发现除了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 (float) 使用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)
    

    【讨论】:

    • 确实,没有dtype=None,@ali_m 给出的答案是行不通的。不幸的是,我无法指定dtype=None,因为我不希望所有数据都以字符串形式读取,并且不希望通过genfromtxt 自动转换为其他内容。我只能编写自己的文件读取程序。
    • 为什么不在加载过程中使用简单的字段名称,然后将它们更改为带有有趣字符的东西?查看我的编辑。
    • 虽然可以在事后修改数组的dtype.names,但这样做仍然需要修改代码,因为我不知道先验输入中的哪一行文件包含头信息。有几种不同的输入文件格式,在某些情况下,我使用genfromtxt 内置功能来确定哪一行包含列名。由于我现在必须编写读取文件的代码以确定names 参数,所以我也不妨编写代码自己读取数据。
    猜你喜欢
    • 1970-01-01
    • 2020-05-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-28
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    相关资源
    最近更新 更多