В коде, скомпилированном Numba, как получить доступ к конкретному полю numba.types.Record без жесткого кодирования имени поля? - PullRequest
0 голосов
/ 12 июля 2020

У меня ситуация, когда я должен получить доступ к полю структурированного массива по индексу, а не по имени. Например:

array[1]  # of course in reality this number is dynamic

Где dtype массива:

Record(Date[type=int64;offset=0],Tag[type=int64;offset=8],Key[type=int64;offset=16])

Но если я попытаюсь это сделать, это не удастся:

Invalid use of Function(<built-in function getitem>) with argument(s) of type(s): (Record(Date[type=int64;offset=0],Tag[type=int64;offset=8],Key[type=int64;offset=16]), int64)

По сути, говоря мне, что нет версии getitem, которая принимает int.

Если я пытаюсь получить доступ по имени столбца, он работает:

array['Date']  # <== This is just fine

Итак, я попытался создать простую функцию который преобразует индекс в имя столбца (должен был возвращать массив кодов ascii, потому что Numba, похоже, не поддерживает строки):

@njit([types.Array(types.uint8, 1, 'C', readonly=True)(types.int16)], nogil=True)
def get_column_name_for_index(idx):
    if idx == 0:
        return np.frombuffer(b'Date', dtype=np.uint8)
    if idx == 1:
        return np.frombuffer(b'Tag', dtype=np.uint8)

    return np.frombuffer(b'Key', dtype=np.uint8)

Итак, я мог бы попробовать:

array[get_column_name_for_index(1)]

Но это не удается, потому что я не могу использовать там массив uint8.

Я подумал, что если бы я мог преобразовать этот массив unit8 в строку и использовать эту строку для доступа к столбцу с помощью название. Я нашел способ, но все же, когда он доходит до этой точки, он терпит неудачу с:

Недопустимое использование Function () с аргументом (ами) типа (ов): (Record (Date [type = int64; offset = 0], тег [type = int64; offset = 8], Key [type = int64; offset = 16]), unicode_type)

Как мне получить доступ к определенному полю (это будет определено во время выполнения) из numba.types.Record по индексу или по имени, или любым другим способом?

1 Ответ

0 голосов
/ 12 июля 2020

Не прибегая к numba, вы можете индексировать поля по номеру, используя атрибут dtype.names:

In [139]: A = np.zeros(3, 'U3,i,f')                                                                  
In [140]: A                                                                                          
Out[140]: 
array([('', 0, 0.), ('', 0, 0.), ('', 0, 0.)],
      dtype=[('f0', '<U3'), ('f1', '<i4'), ('f2', '<f4')])
In [141]: A['f1']                                                                                    
Out[141]: array([0, 0, 0], dtype=int32)
In [142]: A.dtype.names                                                                              
Out[142]: ('f0', 'f1', 'f2')
In [143]: A[A.dtype.names[1]]                                                                        
Out[143]: array([0, 0, 0], dtype=int32)
...