numpy первое ненулевое значение векторов в многомерном массиве - PullRequest
0 голосов
/ 07 февраля 2020

У меня есть 3-мерная numpy ndarray-форма (i, j, k), где каждая строка представляет собой массив из нескольких одинаковых по размеру векторов.

Я хотел бы извлечь массив (i, k) в форме, так чтобы каждый элемент строк содержал первый ненулевой элемент своей группы векторов "j"

Итак, в основном, учитывая массив, такой как:

[
  [
    [0 , 10 , 12 ,  0 , 4],
    [0 ,  0 , 13 ,  1 , 2],
    [12, 14 ,  1 , 12 , 8]
  ],

  [
    [5 , 17 , 12 ,  9 , 0],
    [0 ,  0 , 13 ,  1 , 0],
    [12, 14 ,  1 , 12 , 8]
  ],

  [
    [0 , 0  , 19 ,  0 , 9],
    [2 , 6  , 13 ,  0 , 2],
    [12, 14 ,  1 , 12 , 8]
  ]
]

Я ищу, чтобы найти что-то вроде:


[
  [12, 10, 12, 1, 4],
  [5 , 17, 12, 9, 8],
  [2 , 6, 19, 12, 9]
]


Как найти результаты эффективно?

import numpy as np

i,j,k = 3, 5, 10 #in real problem, these are pretty large
arr = np.random.randint(0, 10000, (i,j,k))
#????????

Ответы [ 3 ]

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

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

def find_non_zero(lst):
  for num in lst:
    if num != 0:
      return num

Сначала мы определим очень простую вспомогательную функцию find_non_zero, которая получает одномерный список в качестве входных данных и возвращает первый не нулевой вход. Затем эта функция используется, когда мы l oop на каждый столбец двумерного массива в arrays, предоставленный трехмерный входной массив.

import numpy as np

arrays = [
  [
    [0 , 10 , 12 ,  0 , 4],
    [0 ,  0 , 13 ,  1 , 2],
    [12, 14 ,  1 , 12 , 8]
  ],

  [
    [5 , 17 , 12 ,  9 , 0],
    [0 ,  0 , 13 ,  1 , 0],
    [12, 14 ,  1 , 12 , 8]
  ],

  [
    [0 , 0  , 19 ,  0 , 9],
    [2 , 6  , 13 ,  0 , 2],
    [12, 14 ,  1 , 12 , 8]
  ]
]

final_result = []
for array in arrays:
  array = np.array(array).T  
  final_result.append([find_non_zero(col) for col in array])

print(final_result)

Это дает следующий вывод.

[[12, 10, 12, 1, 4], [5, 17, 12, 9, 8], [2, 6, 19, 12, 9]]

Numpy Оператор транспонирования .T пригодится, потому что он позволяет нам l oop через двумерные массивы по столбцам вместо строки по умолчанию. Для получения дополнительной информации об операторе транспонирования прочитайте официальную документацию .

Я был бы рад ответить на любые дополнительные вопросы, которые могут у вас возникнуть.

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

Используйте применить вдоль оси, а затем применить ненулевую функцию и получить первый элемент в нужной оси

np.apply_along_axis(lambda e: e[np.nonzero(e)][0], 1, x)

ИЛИ

np.apply_along_axis(lambda e: e[(e!=0).argmax()], 1, x)

Выход

array([[12, 10, 12,  1,  4],
       [ 5, 17, 12,  9,  8],
       [ 2,  6, 19, 12,  9]])
0 голосов
/ 07 февраля 2020

Используя простое транспонирование https://docs.scipy.org/doc/numpy/reference/generated/numpy.transpose.html и расширенное индексирование https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#advanced -индексирование , решение выглядит так:

import numpy as np

a = np.array([
  [
    [0 , 10 , 12 ,  0 , 4],
    [0 ,  0 , 13 ,  1 , 2],
    [12, 14 ,  1 , 12 , 8]
  ],

  [
    [5 , 17 , 12 ,  9 , 0],
    [0 ,  0 , 13 ,  1 , 0],
    [12, 14 ,  1 , 12 , 8]
  ],

  [
    [0 , 0  , 19 ,  0 , 9],
    [2 , 6  , 13 ,  0 , 2],
    [12, 14 ,  1 , 12 , 8]
  ]
])

# swapping the 0 and 1 axes, to make the rest of the code easier
a = a.transpose((1, 0, 2))

# initialising result to zeroes, same shape as a single layer of the transposed a
result = np.zeros(a[0].shape, np.int32)

# one layer at a time
for layer in a:
    # as soon as result contains no more zeroes, done
    if len(result[result == 0]) == 0:
        break
    else:
        # replace all values of result that are zero
        # with values from the same location in layer
        result[result == 0] = layer[result == 0]

print(result)

Печать:

[[12 10 12  1  4]
 [ 5 17 12  9  8]
 [ 2  6 19 12  9]]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...