Получите доступ к элементам Matrix по списку индексов в Python, чтобы применить max (val, 0.5) к каждому значению без цикла for - PullRequest
0 голосов
/ 28 февраля 2019

Я знаю, как получить доступ к элементам в векторе, используя индексы:

test = numpy.array([1,2,3,4,5,6])
indices = list([1,3,5])
print(test[indices])

, что дает правильный ответ: [2 4 6]

Но я пытаюсь сделать то же самоевещь, использующая 2D-матрицу, что-то вроде:

currentGrid = numpy.array(  [[0,   0.1],
                             [0.9, 0.9],
                             [0.1, 0.1]])
indices = list([(0,0),(1,1)])
print(currentGrid[indices])

. Это должно отобразить меня "[0.0 0.9]" для значения в (0,0) и в (1,1) в матрице.Но вместо этого он отображает «[0,1 0,1]».Также, если я попытаюсь использовать 3 индекса с:

indices = list([(0,0),(1,1),(0,2)])

Теперь я получаю следующую ошибку:

Traceback (most recent call last):
  File "main.py", line 43, in <module>
    print(currentGrid[indices])
IndexError: too many indices for array

В конечном итоге мне нужно применить простую операцию max () для всех элементовпо этим показателям и нужен самый быстрый способ сделать это в целях оптимизации.

Что я делаю не так?Как я могу получить доступ к определенным элементам в матрице, чтобы сделать некоторые операции с ними очень эффективным способом (без использования списка или цикла).

Ответы [ 3 ]

0 голосов
/ 28 февраля 2019

2D-индексы должны быть доступны следующим образом:

print(currentGrid[indices[:,0], indices[:,1]])

Индексы строк и индексов столбцов должны передаваться отдельно в виде списков.

0 голосов
/ 28 февраля 2019

Уже есть несколько отличных ответов на вашу проблему.Вот только быстрое и грязное решение для вашего конкретного кода:

for i in indices:
    print(currentGrid[i[0],i[1]])

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

Если вы не хотите использовать цикл for, вам нужно сделать следующее:

Предположим, у вас есть 3 значения вашей 2D-матрицы (с размерами x1 и x2, к которым вы хотите получить доступ. Значения имеют «координаты» (индексы) V1(x11|x21), V2(x12|x22), V3(x13|x23). Затем для каждогоизмерение вашей матрицы (2 в вашем случае) вам нужно создать список с индексами для этого измерения ваших точек.В этом примере вы создадите один список с индексами x1: [x11,x12,x13] и один список сx2 индексы ваших очков: [x21,x22,x23]. Затем вы объединяете эти списки и используете их в качестве индекса для матрицы:

indices = [[x11,x12,x13],[x21,x22,x23]]

или как вы пишете:

indices = list([(x11,x12,x13),(x21,x22,x23)])

Теперь с точками, которые вы использовали ((0,0),(1,1),(2,0)) - обратите внимание, что вам нужно использовать (2,0) вместо (0,2), потому что в противном случае это было бы вне диапазона:

indices = list([(0,1,2),(0,1,0)])
print(currentGrid[indices])

Это будетдать вам 0, 0.9, 0.1. И в этом списке вы можете затем применить команду max (), если хотите (просторассмотрите весь свой вопрос):

maxValue = max(currentGrid[indices])

Edit2:

Вот пример того, как вы можете преобразовать свой исходный индексный список, чтобы получить его правильную форму:

originalIndices = [(0,0),(1,1),(2,0)]

x1 = []
x2 = []

for i in originalIndices:
    x1.append(i[0])
    x2.append(i[1])

newIndices = [x1,x2]
print(currentGrid[newIndices])

Edit3:

Я не знаю, можно ли применить max(x,0.5) к массиву с использованием цикла.Но вы могли бы использовать Панды вместо этого.Вы можете преобразовать свой список в серию панд, а затем применить лямбда-функцию:

import pandas as pd
maxValues = pd.Series(currentGrid[newIndices]).apply(lambda x: max(x,0.5))

. Это даст вам массив панд, содержащий 0.5,0.9,0.5, который вы можете просто привести обратно к списку maxValues = list(maxValues).

Только одно примечание: в фоновом режиме у вас всегда будет работать какой-то цикл, также с этой командой.Я сомневаюсь, что вы получите намного лучшую производительность от этого.Если вы действительно хотите повысить производительность, используйте цикл for вместе с numba (вам просто нужно добавить декоратор к вашей функции) и выполняйте его параллельно.Или вы можете использовать библиотеку multiprocessing и функцию Pool, см. здесь .Просто чтобы дать вам вдохновение.

Edit4:

Случайно я увидел эту страницу сегодня, которая позволяет делать именно то, что вы хотите с Numpy.Решение (рассмотрите вектор newIndices из моего Edit2) вашей проблемы:

maxfunction = numpy.vectorize(lambda i: max(i,0.5))
print(maxfunction(currentGrid[newIndices]))
0 голосов
/ 28 февраля 2019

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

idx_i, idx_j = zip(*[(0, 0), (1, 1), (0, 2)])
print currentGrid[idx_j, idx_i]
# [0.0, 0.9, 0.1]

Обратите внимание, что первый элемент при индексации массивов является последним измерением, например: (y, x).Я предполагаю, что вы определили свой как (x, y), иначе вы получите IndexError

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