Реализация группового сбоя на Cython с помощью NameError - PullRequest
1 голос
/ 14 октября 2019

Я пытаюсь ускорить десятки звонков, которые я делаю в pandas groupby, используя оптимизированные для Cython функции. К ним относятся прямые групповые, групповые с рейтингом и другие. У меня есть один, который выполняет групповую работу, которая выполняется в моей записной книжке, но не при вызове я получаю NameError.

Вот тестовый код из моей записной книжки (в 3 ячейках там)

%%cython
def _set_indices(keys_as_int, n_keys):
    import numpy

    cdef int i, j, k
    cdef object[:, :] indices = [[i for i in range(0)] for _ in range(n_keys)]

    for j, k in enumerate(keys_as_int):
        indices[k].append(j)
    return [([numpy.array(elt) for elt in indices])]



def group_by(keys):
    _, first_occurrences, keys_as_int = np.unique(keys, return_index=True, return_inverse=True)
    n_keys = max(keys_as_int) + 1
    indices = [[] for _ in range(max(keys_as_int) + 1)]
    print(str(keys_as_int) + str(n_keys) + str(indices))
    indices = _set_indices(keys_as_int, n_keys)
    return indices



%%timeit
result = group_by(['1', '2', '3', '1', '3'])
print(str(result))

Ошибка, которую я получаю:

<ipython-input-20-3f8635aec47f> in group_by(keys)
  4     indices = [[] for _ in range(max(keys_as_int) + 1)]
  5     print(str(keys_as_int) + str(n_keys) + str(indices))
 ----> 6     indices = _set_indices(keys_as_int, n_keys)
      7     return indices

NameError: name '_set_indices' is not defined

Может кто-нибудь объяснить, связано ли это с ноутбуком или я что-то не так сделал с использованием Cython, я новичок в этом.

Также приветствуются любые подсказки для получения строго типизированного решения с минимальным количеством попаданий в кеш.

1 Ответ

1 голос
/ 14 октября 2019

Вам нужно поместить вашу _set_indices функцию в ту же ячейку , или вам нужно явно импортировать ее. Из Компиляция с помощью ноутбука Jupyter Документация :

Обратите внимание, что каждая ячейка будет скомпилирована в отдельный модуль расширения.

После компиляции у вас есть глобальное имя _set_indices, но это не делает его доступным как глобальное в отдельном модуле расширения для функции group_by().

Вам нужно будет поместить два определения функций в одну и ту же ячейку или создать отдельный модуль для служебных функций.

Обратите внимание, что есть и другая проблема с кодом;вы не можете просто создать типизированное представление памяти из списка целых чисел:

Traceback (most recent call last):
  File "so58378716.pyx", line 22, in init so58378716
    result = group_by(['1', '2', '3', '1', '3'])
  File "so58378716.pyx", line 19, in so58378716.group_by
    indices = _set_indices(keys_as_int, n_keys)
  File "so58378716.pyx", line 6, in so58378716._set_indices
    cdef object[:, :] indices = [[i for i in range(0)] for _ in range(n_keys)]
  File "stringsource", line 654, in View.MemoryView.memoryview_cwrapper
  File "stringsource", line 349, in View.MemoryView.memoryview.__cinit__
TypeError: a bytes-like object is required, not 'list'

Вы должны будете создать фактический массив numpy или использовать cython.view.array объект ,или array.array.

...