Python NumPy Arrays - PullRequest
       6

Python NumPy Arrays

3 голосов
/ 13 июля 2011

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

X = [1, 2, 3, 1, 2, 3, 1, 2, 3]

или

X = [0.2, 0.4, 0.6, 0.8, 0.2, 0.4, 0.6, 0.8, 0.2, 0.4, 0.6, 0.8, 0.2, 0.4, 0.6, 0.8]

Игнорировать первую часть сообщения.

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

Я прошу прощения, если я вызвал какую-то путаницу ранее. Английский не мой язык, и иногда мне трудно что-то объяснять.

Это код, который сделал работу за меня:

    myIter = linspace(1, N, N)
    for x in myIter:
        for y in myIter:
            index = ((x - 1)*N + y) - 1
            X[index] = x / (N+1)
            Y[index] = y / (N+1)

Пользователь вводит N. И длина X, Y составляет N * N.

Ответы [ 5 ]

12 голосов
/ 13 июля 2011

Вы можете использовать функцию tile.Из примеров:

>>> a = np.array([0, 1, 2])
>>> np.tile(a, 2)
array([0, 1, 2, 0, 1, 2])

С помощью этой функции вы также можете сразу изменить форму массива, как они делают в других ответах, с изменением формы (определив «повторы» - это больше измерений):

>>> np.tile(a, (2, 1))
array([[0, 1, 2],
       [0, 1, 2]])

Добавление : и небольшое сравнение разницы в скорости между встроенной функцией tile и умножением:

In [3]: %timeit numpy.array([1, 2, 3]* 3)
100000 loops, best of 3: 16.3 us per loop
In [4]: %timeit numpy.tile(numpy.array([1, 2, 3]), 3)
10000 loops, best of 3: 37 us per loop

In [5]: %timeit numpy.array([1, 2, 3]* 1000)
1000 loops, best of 3: 1.85 ms per loop
In [6]: %timeit numpy.tile(numpy.array([1, 2, 3]), 1000)
10000 loops, best of 3: 122 us per loop 

EDIT

Вывод кода, который вы дали в своем вопросе, также может быть достигнут следующим образом:

arr = myIter / (N + 1)
X = numpy.repeat(arr, N)
Y = numpy.tile(arr, N)

Таким образом вы можете избежать зацикливания массивов (что является одним из больших преимуществ использованияNumPy).Полученный код проще (если вы, конечно, знаете функции, см. Документацию по repeat и tile ) и быстрее.

2 голосов
/ 13 июля 2011

Если вы хотите создать списки повторяющихся значений, вы можете использовать умножение списков / кортежей ...

>>> import numpy
>>> numpy.array((1, 2, 3) * 3)
array([1, 2, 3, 1, 2, 3, 1, 2, 3])
>>> numpy.array((0.2, 0.4, 0.6, 0.8) * 3).reshape((3, 4))
array([[ 0.2,  0.4,  0.6,  0.8],
       [ 0.2,  0.4,  0.6,  0.8],
       [ 0.2,  0.4,  0.6,  0.8]])

Спасибо за обновление вашего вопроса - теперь все намного понятнее. Хотя я думаю, ответ joris является лучшим в этом случае (потому что он более читабелен), я укажу, что новый код, который вы разместили, также можно обобщить так:

>>> arr = numpy.arange(1, N + 1) / (N + 1.0)
>>> X = arr[numpy.indices((N, N))[0]].flatten()
>>> Y = arr[numpy.indices((N, N))[1]].flatten()

Во многих случаях при использовании numpy можно избежать циклов while, используя мощную систему индексации numpy. Как правило, когда вы используете массив I для индексирования массива A, результатом является массив J той же формы, что и I. Для каждого индекса i в I значение A[i] присваивается соответствующей позиции в J. Например, скажем, у вас есть arr = numpy.arange(0, 9) / (9.0), и вы хотите значения в индексах 3, 5 и 8. Все, что вам нужно сделать, это использовать numpy.array([3, 5, 8]) в качестве индекса для arr:

>>> arr
array([ 0.        ,  0.11111111,  0.22222222,  0.33333333,  0.44444444,
        0.55555556,  0.66666667,  0.77777778,  0.88888889])
>>> arr[numpy.array([3, 5, 8])]
array([ 0.33333333,  0.55555556,  0.88888889])

Что, если вам нужен 2-й массив? Просто введите двумерный индекс:

>>> arr[numpy.array([[1,1,1],[2,2,2],[3,3,3]])]
array([[ 0.11111111,  0.11111111,  0.11111111],
       [ 0.22222222,  0.22222222,  0.22222222],
       [ 0.33333333,  0.33333333,  0.33333333]])

>>> arr[numpy.array([[1,2,3],[1,2,3],[1,2,3]])]
array([[ 0.11111111,  0.22222222,  0.33333333],
       [ 0.11111111,  0.22222222,  0.33333333],
       [ 0.11111111,  0.22222222,  0.33333333]])

Поскольку вам не нужно постоянно вводить подобные индексы, вы можете генерировать их автоматически - с помощью numpy.indices:

>>> numpy.indices((3, 3))
array([[[0, 0, 0],
        [1, 1, 1],
        [2, 2, 2]],

       [[0, 1, 2],
        [0, 1, 2],
        [0, 1, 2]]])

В двух словах, так работает приведенный выше код. (Также проверьте numpy.mgrid и numpy.ogrid - которые предоставляют немного более гибкие генераторы индекса.)

Поскольку многие numpy операции векторизованы (то есть они применяются к каждому элементу в массиве), вам просто нужно найти правильные индексы для задания - циклы не требуются.

2 голосов
/ 13 июля 2011
print numpy.array(range(1, 4) * 3)
print numpy.array(range(1, 5) * 4).astype(float) * 2 / 10
1 голос
/ 13 июля 2011

Я не совсем уверен, что вы пытаетесь сделать, но предположительно: если у вас есть одномерный массив, и вам нужно сделать его 2D, вы можете использовать метод изменения классов массивов.

    >>> import numpy
    >>> a = numpy.array([1,2,3,1,2,3])
    >>> a.reshape((2,3))
    array([[1, 2, 3],
          [1, 2, 3]])
1 голос
/ 13 июля 2011
import numpy as np   

X = range(1,4)*3
X = list(np.arange(.2,.8,.2))*4

они составят два ваших списка соответственно. Надеюсь, это то, что вы спрашивали

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