Есть ли способ объявить структурированный массив, который имеет строковое поле произвольной длины? - PullRequest
0 голосов
/ 02 мая 2020

Это уже не давало мне покоя, но я не нашел удовлетворительного решения.

Если вы объявляете структурированный массив с полем, содержащим строки, как вы можете установить dtype этого поля на что-то, чтобы вам не приходилось беспокоиться о длине строк в этом поле ?

С floats и ints это намного проще. До сих пор я всегда использовал 'i4' или 'f4' в качестве соответствующих dtypes и никогда не имел проблем (хотя я не уверен, что это плохая практика, не стесняйтесь указывать на это). И в маловероятном случае, что числа на самом деле слишком длинные для этих dtypes, Python говорит мне об этом, поднимая OverflowError. Но если строка слишком длинная, она просто молча обрывается.

Есть ли способ объявить строку dtype, чтобы вам не нужно было точно знать, как долго (будут) ваши строки, которые вы хотите сохранить в структурированном массиве, до его создания? Я имею в виду, что вы всегда можете угадать и предположить, что, скажем, 'U30', вероятно, будет достаточно и надеяться на лучшее, но мне это не очень нравится. До сих пор мой обходной путь всегда заключался в использовании объекта dtype 'O', потому что он просто берет что угодно, но мне это тоже никогда не нравилось.

Я думаю, что в случае ints или floats, вы также можете использовать ìnt и float в качестве dtypes, не беспокоясь о количестве битов, необходимых для хранения данных. Почему это не реализовано таким же образом для строк при использовании str в качестве dtype? Я следовал по этой цепочке сообщений , а в github объясняется, что str dtype по умолчанию равен пустой строке, если я не ошибаюсь.

В соответствии с документацией numpy для объектов типа данных :

Чтобы использовать реальные строки в Python 3, используйте U или np.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)

1 Ответ

1 голос
/ 02 мая 2020

Все варианты, которые вы пробовали, делают одно и то же, определяют «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 выбирает использование Объект dtype для всех его строк. Фиксированная длина строки numpy приемлема, если строки имеют одинаковый размер и знают заранее, например, np.array(['one','two','three', 'four', 'five'])

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...