#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]]
Решение немного сложное по сравнению с чем-то родным, но работает на удивление быстро. Это позволяет легко управлять сбором индексов и поддерживает быстрое преобразование в поток индексов по требованию.