Как вручную выбирать значения из массива

#python #arrays #numpy #multidimensional-array

#python #массивы #numpy #многомерный-массив

Вопрос:

Например, у меня есть матричный массив

 a=np.arrange(25).shape(5,5)
[[ 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]]
 

Как мне создать одномерный массив элементов, которые я хотел бы выбрать вручную? Например [2,3], [4,1], [1,0] и [2,2], так что я получаю следующее:

 b=[13, 21, 5, 12]
 

Массив должен быть ссылкой, а не копией.

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

1. Вы спрашиваете, возможно ли создать несмежное представление массива?

2. Да, я изучал процедуры индексации Numpy, и, похоже, ни одна из функций не предоставляет такую возможность

3. Возможно, вы могли бы написать свой собственный класс с именем something like CustomView для этого как своего рода оболочку a.view() , хотя это, очевидно, было бы медленнее, чем встроенный подход. Хотя кажется, что это было бы неплохо, я согласен, что нет очевидного встроенного решения (что не означает, что встроенного решения не существует).

4. результаты для b должны быть неверными для 2,3 и 4,1

5. @GoldenLion [4,1] действительно был неправ, спасибо

Ответ №1:

Вы можете создать функцию для этого.

 # defining the function
def get_value(matrix, row_list, col_list):
    for i, j in zip(row_list, col_list):
        return matrix[row_list, col_list]

# initializing the array
a = np.arange(0, 25, 1).reshape(5, 5)

# getting the required values and printing
b = get_value(a, [2,4,1,0], [3,1,0,2])

# output
print(b)
 

Редактировать

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

Вопрос заключается в том, чтобы указать значение из b (т. Е. b[0] Которое есть 13 ) и Изменить значение из исходной матрицы a на основе индекса этого переданного значения из b in a .

 def change_the_value(old_mat, val_to_change, new_val):
    mat_coor = np.array(np.matrix(np.where(old_mat == val_to_change)).T)[0]
    old_mat[mat_coor[0], mat_coor[1]] = new_val
 
a = np.arange(0, 25, 1).reshape(5,5)
b = [13, 16, 5, 12]

change_the_value(a, b[0], 0)
 

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

1. Функция работает, но она возвращает новый массив. В моем случае мне нужно иметь возможность изменять исходный массив, поэтому мне нужно представление, а не копия.

2. Вы хотите навсегда изменить значение a ? Ты это хочешь сказать?

3. Мне нужно иметь возможность изменять массив a через b

4. Я думаю, что я неправильно сформулировал это. Изначально a это матрица 5×5, после выполнения задачи вы хотите a быть array([13, 21, 5, 2])

5. Я хочу a остаться прежним, но если я это сделаю b[0]=0 , то a[2,3] должен измениться на ноль

Ответ №2:

 a=np.arange(25).reshape(5,5)
search=[[2,3], [4,1], [1,0], [2,2]]
for row,col in search:
    print(row,col, a[row][col])
 

вывод:

 r c result
2 3 13
4 1 21
1 0 5
2 2 12
 

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

1. Строго говоря, это работает, но включает списки, которые не так быстры, как массивы Numpy. Сейчас я использую то же решение, но со списком кортежей, поскольку они квалифицируются как готовые к использованию индексы. Я думал о более нативном решении Numpy.

Ответ №3:

Прежде всего, я обнаружил, что построение несмежного представления массива Numpy изначально невозможно, поскольку Numpy эффективно использует непрерывную компоновку массива в памяти, что позволяет значительно увеличить скорость.

Вот решение, которое я нашел, которое пока работает лучше всего: вместо представления массива я создаю индексы коллекции, которые я хотел бы обработать [2,3], [4,1], [1,0], [2,2] . Тип коллекции, который я выбрал, — это наборы, из-за исключения дубликатов set().add и set().discard методов, которые не требуют поиска. Поддержание порядка не было необходимости.

Чтобы использовать их для индексации массива, они должны быть преобразованы из набора кортежей set{(2,3),(4,1),(1,0),(2,2)} в кортеж массивов (ndarray([2,4,1,2], ndarray[3,1,0,2]) .

Чего можно добиться, разархивировав набор и создав кортеж массивов:

 import numpy as np
a=np.arrange(25).shape(5,5)
>>>[[ 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]]

my_set = {(2,3),(4,1),(1,0),(2,2)}
uzip_set = list(zip(*my_set))
seq_from_set = (np.asarray(uzip_set[0]),np.asarray(uzip_set[1]))
print(seq_from_set)
>>>(array[2,4,1,2], array[3,1,0,2])
 

И массивом a можно манипулировать, предоставляя такую последовательность индексов:

 b = a[seq_from_set]
print(b)
>>>array[13,21,5,12]  
a[seq_from_set] = 0
print(a)   
 >>>[[ 0  1  2  3  4]
     [ 0  6  7  8  9]
     [10 11  0  0 14]
     [15 16 17 18 19]
     [20  0 22 23 24]]
 

Решение немного сложное по сравнению с чем-то родным, но работает на удивление быстро. Это позволяет легко управлять сбором индексов и поддерживает быстрое преобразование в поток индексов по требованию.