Numpy порядок индексов - PullRequest
       2

Numpy порядок индексов

1 голос
/ 10 февраля 2020

Я не совсем понимаю, как обрабатываются измерения np.zeros ().

У меня есть pandas фрейм данных с некоторыми игрушечными данными

# A toy 3col x 4row Dataframe
a = pd.DataFrame([[1,2,3],[4,5,6],[7,8,9],[10,11,12]],columns=['colA','colB','colC'])
b = pd.DataFrame([[40,41,42],[43,44,45],[46,47,48],[49,50,51]],columns=['colA','colB','colC'])


  colA colB colC
0    1    2    3
1    4    5    6
2    7    8    9
3   10   11   12

Я хочу получить эти два кадры данных в массив измерений 3D numpy (4 строки, 3 протокола, 2 канала), поэтому я могу рассчитать статистику между двумя кадрами данных (например, среднее, максимальное значения и т. д. c ...)

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

c = np.zeros((4, 3, 2))
c[:,:,0] = a.values
c[:,:,1] = b.values

array([[[ 1., 40.],
        [ 2., 41.],
        [ 3., 42.]],

       [[ 4., 43.],
        [ 5., 44.],
        [ 6., 45.]],

       [[ 7., 46.],
        [ 8., 47.],
        [ 9., 48.]],

       [[10., 49.],
        [11., 50.],
        [12., 51.]]])

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

c = np.zeros((2,4,3))
c[0,:,:] = a.values
c[1,:,:] = b.values
array([[[ 1.,  2.,  3.],
        [ 4.,  5.,  6.],
        [ 7.,  8.,  9.],
        [10., 11., 12.]],

       [[40., 41., 42.],
        [43., 44., 45.],
        [46., 47., 48.],
        [49., 50., 51.]]])

Я не понимаю эту логику c. Почему третье измерение (канал) является первым индексом, а не последним?

Когда я вычисляю среднее значение по двум каналам, я должен сделать это, используя axis=0, что очень запутанно. Любой, кто смотрит на код, подумает, что это среднее по столбцам, а не среднее между каналами.

Я что-то не так делаю?

Ответы [ 3 ]

1 голос
/ 10 февраля 2020

Что касается интуиции, это просто типичный способ доступа в большинстве (всех?) Языков программирования. Как правило, когда вы делаете что-то вроде:

my_array[a][b][c][d]

, что более распространено, чем индексирование стиля Numpy с учетом всех языков, вы обычно имеете в виду:

  1. С my_array получить блок a. Это внутренний блок.
  2. Из предыдущего блока получаем блок b. это внутренний блок.
  3. Из предыдущего блока получаем блок c. это внутренний блок.
  4. Из предыдущего блока получите элемент d (который не является блоком, потому что это последние измерения).

Порядок всегда самые внешние измерения для внутреннего самого измерения. Это не имеет ничего общего с изображениями или каналами. Так что в вашем примере, если вы ожидаете, что c[0] вернет канал, а не то, что вы называете строкой, то это интуиция. Вы всегда ставите сначала свое внешнее измерение - так же, как когда у вас есть изображение в виде массива, первые измерения - это строки (высота), а затем столбцы (ширина).

Весь этот разговор игнорирует упорядочения массивов на основе FORTRAN (Matlab) использует это, например) где столбцы являются «внешними» для строк, по определению. Если вы пришли из этих языков (в строку порядка на основе Python и C - столбец), это является распространенным источником недопонимания. В этом случае интуиция просто равна тому, с чем вы привыкли работать с , что субъективно и несколько произвольно.

0 голосов
/ 10 февраля 2020

Это был бы мой подход

>>> x = a.values.reshape((a.shape[0], a.shape[1], 1)) # Convert 2D to 3D - One layer
>>> y = b.values.reshape((b.shape[0], b.shape[1], 1))  # Convert 2D to 3D - Second layer
>>> z = np.concatenate((x, y), axis=2) # Concatenate on 3rd(starts from zero) axis

, который позволил бы получить что-то похожее на ваш массив, и это правильно.

array([[[ 1, 40],
        [ 2, 41],
        [ 3, 42]],

       [[ 4, 43],
        [ 5, 44],
        [ 6, 45]],

       [[ 7, 46],
        [ 8, 47],
        [ 9, 48]],

       [[10, 49],
        [11, 50],
        [12, 51]]])

Кроме того, если вы хотите визуально увидеть массив в фрейме данных (только для проверки)

>>> pd.DataFrame(z.tolist())
          0         1         2
0   [1, 40]   [2, 41]   [3, 42]
1   [4, 43]   [5, 44]   [6, 45]
2   [7, 46]   [8, 47]   [9, 48]
3  [10, 49]  [11, 50]  [12, 51]
0 голосов
/ 10 февраля 2020

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

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