Как определить соседние элементы из 1D массива?

#python #arrays #python-3.x #indexing #finite-element-analysis

#python #массивы #python-3.x #индексирование #анализ конечных элементов

Вопрос:

Я работаю над кодом анализа конечных элементов, и в настоящее время у меня есть одномерный массив, в котором перечислены значения плотности элементов следующим образом:
x = np.единицы (12), где индекс — это номер элемента 0, 1, 2, …, 10, 11
Элементы при построении графика выглядят так:

 0 - 3 - 6 - 9
1 - 4 - 7 - 10
2 - 5 - 8 - 11
 

Я устанавливаю количество элементов в направлении x и y (в данном случае 4 в x и 3 в y), однако мне трудно определить элементы окружения. Мне нужно найти способ определить 3, 5 или 8 элементов, которые окружают заданные элементы. Например, если я выбираю элемент 0, окружающие элементы равны 1, 3, 4 или, если я выбираю элемент 6, окружающие элементы равны 3, 4, 7, 9, 10 или если, если я выбираю элемент 7, окружающие элементы равны 3, 4, 5, 6, 8, 9, 10, 11 …
Конечной целью здесь было бы ввести радиус и на его основе определить номера элементов, окружающих выбранный элемент. Любой совет или помощь в этом были бы весьма признательны. По какой-то причине я не могу определить логику для этого в python.

Комментарии:

1. Так это 2d или 1d?

2. Разве не было бы больше смысла .reshape((4,3)) работать с ним в 2D?

3. Вы можете видеть шаблон, верно? Вверх N-1 , вниз N 1 , влево N-height , вправо N height .

4. if I select element 0 — как выбрать элемент 0?

Ответ №1:

определите логику для этого

  • Одномерный массив из 6 элементов имеет индексы — [0,1,2,3,4,5]
  • Предлагаемая форма — 2 строки и 3 столбца — M,N = 2,3 .
  • для любого элемента index ( i ) его строка и столбец c,r = divmod(i,M)
  • Соседний столбец, индексы строк будут
    •  cplus,cminus = c   1, c - 1
      rplus, rminus = r   1, r - 1
      cplus,r
      cminus,r
      c,rplus
      c,rminus
      cplus,rplus
      cplus,rminus
      cminus,rplus
      cminus,rminus
       
  • эти 2d-индексы необходимо преобразовать в 1d-индексы с помощью (col * M) row

Например

 [0,1,2,3,4,5]
M,N = 2,3
'''
0  2  4
1  3  5
'''
 
  • 2d-индекс элемента 4 c,r = divmod(4,M) равен —> (2,0) (col, строка)
  • один из 2d-индексов его соседа c,rplus — > (2,1)
  • 1d-индекс этого соседа (2 * M) 1 равен —> 5
  • после преобразования 2d-индексов соседей в 1d вам нужно будет проверить и отбросить некоторые, которые не имеют смысла.
    • элемент 4 находится в правом верхнем углу и не имеет каких-либо соседей, например c,rminus , которые были бы (2,-1) , что не имеет смысла. Или cplus,r (3,0) что также не имеет смысла.

Предостережение — я НЕ пытался тщательно протестировать это.


Вот функция, которая возвращает вызываемый объект.

 import operator
def get_neighbors(index, shape=(M,N)):
    '''Returns a callable.

    (M,N) --> (number_of_rows, number_of_columns)
    '''
    M, N = shape
    # 2d index
    c, r = divmod(index, M)
    print(f'2d index: {(c,r)}')
    # neighbors
    cplus, cminus = c   1, c - 1
    rplus, rminus = r   1, r - 1
    # dot product of (c,cplus,cminus) and (r,rplus,rminus)?
    neighbors = [
        (cminus, rminus),
        (cminus, r),
        (cminus, rplus),
        (c, rplus),
        (cplus, rplus),
        (cplus, r),
        (cplus, rminus),
        (c, rminus),
    ]
    # print(neighbors)

    # validate/filter
    neighbors = [
        (col, row) for col, row in neighbors if (0 <= col < N) and (0 <= row < M)
    ]
    # print(neighbors)

    # 1d indices
    one_d = [(col * M)   row for col,row in neighbors]
    # print(one_d)
    return operator.itemgetter(*one_d)
 

Попробуйте.

 >>> a = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't']

>>> M,N = 4,5    # nrows, ncols

'''
[['a' 'e' 'i' 'm' 'q']
 ['b' 'f' 'j' 'n' 'r']
 ['c' 'g' 'k' 'o' 's']
 ['d' 'h' 'l' 'p' 't']]
'''

>>> # i's neighbors
>>> q = get_neighbors(a.index('i'),(M,N))
2d index: (2, 0)
>>> q(a)
('e', 'f', 'j', 'n', 'm')
>>>
>>> # k's neighbors
>>> q = get_neighbors(a.index('k'),(M,N))
2d index: (2, 2)
>>> q(a)
('f', 'g', 'h', 'l', 'p', 'o', 'n', 'j')
>>>
>>> # q's neighbors
>>> q = get_neighbors(a.index('q'),(M,N))
2d index: (4, 0)
>>> q(a)
('m', 'n', 'r')
>>>
 

i соседи для разных форм

 >>> M,N = 5,4
>>> q = get_neighbors(a.index('i'),(M,N))
2d index: (1, 3)
>>> q(a)
('c', 'd', 'e', 'j', 'o', 'n', 'm', 'h')
>>> M,N = 10,2
>>> q = get_neighbors(a.index('i'),(M,N))
2d index: (0, 8)
>>> q(a)
('j', 't', 's', 'r', 'h')
>>> M,N = 2,10
>>> q = get_neighbors(a.index('i'),(M,N))
2d index: (4, 0)
>>> q(a)
('g', 'h', 'j', 'l', 'k')
>>>
 

В документах Numpy есть хорошая дискуссия о создании / обработке 1d-объекта как Nd-объекта — компоновка внутренней памяти ndarray

То, как вы изобразили свое преобразование 1d -> 2d, использовало основную схему столбцов. Я привык думать, что строка-основная — я написал функцию для принятия / ожидания аргумента (nrows, ncols) shape , но внутри функции я как бы переключился на обработку основного столбца. Мне приходилось быть осторожным, так что, возможно, это был плохой дизайн.