有没有办法声明一个具有任意长度字符串字段的结构化数组?

Is there a way to declare a structured array that has a string field of arbitrary lengh?

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

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

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

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

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

根据 data type objects 上的 numpy 文档:

To use actual strings in Python 3 use U or np.unicode_.

所以我想我在下面的示例中尝试了一些东西,但是(正如预期的那样)none 它们起作用了。

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)

您尝试的所有变体都做同样的事情,定义一个 '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 选择对其所有字符串使用对象数据类型。 numpy 固定字符串长度适用于字符串往往大小相同且提前知道的情况,例如np.array(['one','two','three', 'four', 'five'])