【问题标题】:Is there a way to declare a structured array that has a string field of arbitrary lengh?有没有办法声明一个具有任意长度的字符串字段的结构化数组?
【发布时间】:2020-05-01 23:53:56
【问题描述】:

这已经困扰我一段时间了,但我还没有真正找到令人满意的解决方案。

如果你声明一个包含字符串的字段的结构化数组,你如何设置该字段的dtype 某个值,这样你就不必担心该字段中字符串的长度?

有了floatsints 就容易多了。到目前为止,我一直使用 'i4''f4' 作为各自的 dtypes 并且从未遇到任何问题(尽管我不确定这是否是不好的做法,请随时指出)。在不太可能的情况下,对于这些 dtypes 来说,数字实际上太长了,Python 通过提高 OverflowError 来告诉我。但如果一根弦太长,它就会被无声地切断。

有什么方法可以声明字符串 dtype,这样您就不必在创建之前确切知道要在结构化数组中存储的字符串(将要)多长时间?我的意思是你总是可以猜测并假设'U30' 可能就足够了,并希望最好,但我真的不喜欢那样。到目前为止,我的解决方法一直是使用对象 dtype 'O',因为它只需要任何东西,但我也从来没有真正喜欢过。

我认为在intsfloats 的情况下,您也可以使用ìntfloat 作为数据类型,而不必担心存储数据所需的位数。为什么在使用 str 作为 dtype 时对字符串的实现方式不同?我关注了这个chain of posts,在github issue中解释了str dtype默认为空字符串,如果我没记错的话。

根据data type objects 上的numpy 文档:

要在 Python 3 中使用实际字符串,请使用 Unp.unicode_

所以我想我在下面的示例中尝试了几件事,但是(正如预期的那样)它们都不起作用。

import numpy as np


array = np.array(
    [
        ('Apple', 'green', 'round', 'fresh', 'good', 10e4, np.pi)], dtype=[
        ('fruit', np.str_), ('color', np.unicode_), ('shape', np.dtype(str)),
        ('state', str), ('taste', 'U2'), ('weight', 'i4'), ('radius', float)
    ]
)

# this causes OverflowError: Python int too large to convert to C long
# array[0]['weight'] = 10e10

# this is just 'ignored'
array[0]['color'] = 'red'

print(array)

【问题讨论】:

    标签: python arrays python-3.x numpy structured-array


    【解决方案1】:

    您尝试的所有变体都执行相同的操作,定义一个“U0”。这不仅仅是结构化数组问题。

    dtype=[('fruit', '<U'), ('color', '<U'), ('shape', '<U'), ('state', '<U'), ('taste', '<U2'), ('weight', '<i4'), ('radius', '<f8')])
    

    要么指定更长的长度,如 'U10' 或 'O',对象:

    In [239]: arr = np.array( 
         ...:     [ 
         ...:         ('Apple', 'green', 'round', 'fresh', 'good', 10e4, np.pi)], dtype=[ 
         ...:         ('fruit', 'U10'), ('color', 'O'), ('shape', 'O'), 
         ...:         ('state', 'S10'), ('taste', 'U2'), ('weight', 'i4'), ('radius', float) 
         ...:     ] 
         ...: )                                                                                            
    In [240]: arr                                                                                          
    Out[240]: 
    array([('Apple', 'green', 'round', b'fresh', 'go', 100000, 3.14159265)],
          dtype=[('fruit', '<U10'), ('color', 'O'), ('shape', 'O'), ('state', 'S10'), ('taste', '<U2'), ('weight', '<i4'), ('radius', '<f8')])
    In [241]: arr['color']                                                                                 
    Out[241]: array(['green'], dtype=object)
    In [242]: arr['color']='yellow_green'                                                                  
    In [243]: arr['fruit']                                                                                 
    Out[243]: array(['Apple'], dtype='<U10')
    In [244]: arr['fruit']='pineapple'                                                                     
    In [245]: arr                                                                                          
    Out[245]: 
    array([('pineapple', 'yellow_green', 'round', b'fresh', 'go', 100000, 3.14159265)],
          dtype=[('fruit', '<U10'), ('color', 'O'), ('shape', 'O'), ('state', 'S10'), ('taste', '<U2'), ('weight', '<i4'), ('radius', '<f8')])
    

    pandas 选择对其所有字符串使用 object dtype。 numpy 固定字符串长度是可以的,当字符串往往大小相同并且提前知道时,例如np.array(['one','two','three', 'four', 'five'])

    【讨论】:

    • 谢谢!我忘了提一下,当您创建一个仅包含字符串的普通数组时,numpy 不仅会自动假定正确的 dtype str,而且还会选择适合所有字符的长度。当涉及到结构化数组时,为什么要放弃这种逻辑?
    • 也许在结构化数组中,先初始化dtype,然后相应地存储数据,而在常规数组中则相反?那么在结构化数组中,数据类型决定数据,而在常规数组中,数据决定数据类型?
    • np.array 代码不是我写的,所以不能告诉你why。一种猜测是默认行为已经存在很长时间了,复合 dtype 案例是后来添加的,他们并没有尝试复制所有内容。根据维度和 dtype 分配返回数组,然后填充它是有意义的。首先分析所有数据,如未指定 dtype 时所做的那样,可能需要更多的工作和时间。请记住,结构化数组需要元组列表,而不是简单的嵌套列表。 @mapf
    • 另一种看待这个的方式。指定复合 dtype 是否更像指定 np.str 或 'U3'?较长的数据字符串不会扩展“U3”规范,而裸露的str 是一个开放式规范。
    • 感谢您的时间和精力!很抱歉提出后续问题,但是结构化数组需要元组列表而不是简单的嵌套列表这一事实与 dtypes 有什么关系?我不确定我是否理解您在第二条评论中所说的内容。您自己说过,即使使用裸 str 本身作为 dtype 默认为 'U0'。另外我很抱歉,但我不知道np.strstrU3np.unicode 之间有什么区别。不过我不指望你向我解释。我想我应该在某个时候阅读它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-18
    • 2013-12-22
    • 2023-03-26
    • 1970-01-01
    • 1970-01-01
    • 2018-01-23
    • 1970-01-01
    相关资源
    最近更新 更多