Понимание списка Python для Numpy - PullRequest
3 голосов
/ 02 января 2012

Я ищу метод составления списка или аналогичный в Numpy, чтобы исключить использование цикла for, например. index_values ​​- это список списков в Python-словаре (каждый список содержит различное количество значений индекса), а s - это пустой вектор:

for i in range(33):
    s[index_values[i]] += 4.1

Существует ли метод, позволяющий устранить цикл for?

Ответы [ 2 ]

4 голосов
/ 02 января 2012

Я не до конца понимаю, что это за объект index_values. Но если бы это было ndarray или могло быть преобразовано в ndarray, вы могли бы просто сделать это:

>>> s = numpy.arange(20)
>>> index_values = (numpy.random.random((3, 3)) * 20).astype('i')
>>> s[index_values] = 4
>>> s
array([ 0,  1,  4,  4,  4,  5,  6,  4,  8,  4,  4, 11, 12, 
       13,  4, 15,  4,  4,  4, 19])

Редактировать: Но, похоже, это не сработает в этом случае. Исходя из ваших правок и комментариев, вот метод, который, я думаю, может сработать для вас. Случайный список списков различной длины ...

>>> index_values = [list(range(x, x + random.randrange(1, 5)))
...                 for x in [random.randrange(0,50) for y in range(33)]]

... не сложно преобразовать в массив:

>>> index_value_array = numpy.fromiter(itertools.chain(*index_values), 
                                       dtype='i')

Если вы знаете длину массива, укажите count для лучшей производительности:

>>> index_value_array = numpy.fromiter(itertools.chain(*index_values), 
                                       dtype='i', count=83)

Поскольку ваши правки указывают на то, что вам нужно поведение, подобное гистограмме, простое индексирование не сработает, как указал Роберт Керн. Так что используйте numpy.histogram:

>>> hist = numpy.histogram(index_value_array, bins=range(0, 51))

histogram действительно построен для гистограмм с плавающей запятой. Это означает, что интервалы должны быть немного больше ожидаемых, поскольку последнее значение включено в последний интервал, и поэтому 48 и 49 будут в одном интервале, если мы используем более интуитивно понятный range(0, 50). В результате получается кортеж с массивом n и массивом n + 1 границ bin:

>>> hist
(array([2, 2, 1, 2, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 5, 5, 5, 3, 3, 
        3, 3, 3, 2, 1, 0, 2, 3, 3, 1, 0, 2, 3, 2, 2, 2, 3, 2, 1, 1, 2, 2, 
        2, 0, 0, 0, 1, 0]), 
 array([ 0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 16,
        17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
        34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50]))

Теперь мы можем увеличить счет в 4,1 раза и выполнить сложение векторов:

>>> s = numpy.arange(50, dtype='f')
>>> hist[0] * 4.1 + s
array([  8.2,   9.2,   6.1,  11.2,   8.1,   5. ,   6. ,   7. ,  12.1,
        13.1,  14.1,  15.1,  16.1,  13. ,  18.1,  19.1,  20.1,  37.5,
        38.5,  39.5,  32.3,  33.3,  34.3,  35.3,  36.3,  33.2,  30.1,
        27. ,  36.2,  41.3,  42.3,  35.1,  32. ,  41.2,  46.3,  43.2,
        44.2,  45.2,  50.3,  47.2,  44.1,  45.1,  50.2,  51.2,  52.2,
        45. ,  46. ,  47. ,  52.1,  49. ])

Я понятия не имею, подходит ли это вашим целям, но это кажется хорошим подходом и, вероятно, должно происходить на скорости, близкой к c, так как она использует только numpy и itertools.

1 голос
/ 02 января 2012

А как же:

s[reduce(lambda x,y: x+y, [index_values[x] for x in range(33)], [])] = 4.1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...