Матрица Numpy If / Else Классификация? - PullRequest
0 голосов
/ 30 октября 2018

Допустим, у меня есть матрица M с 3 (или n) столбцами с отрицательными / положительными значениями:

M=[[-0.5,0.5,-1],
   [1,-0.5,-1],
   [-1,-1,-0.5],
   [0.5,1-,1],
   [1,0.5,1]]

Теперь я хочу классифицировать каждую строку по условию и создать четвертый столбец с результатом. Условиями являются комбинации <0 и> 0.

# Just an example of conditions
# The actual amount of conditions is 2^n with n being the amount of columns and 2 because there are variants (<0 and >0)
results = []
if row[0]<0 and row[1]>0 and row[2]>0:
    results.append(1)
elif row[0]>0 and row[1]>0 and row[2]>0:
    results.append(1)
elif row[0]<0 and row[1]<0 and row[2]<0:
    results.append(-1)
elif row[0]<0 and row[1]<0 and row[2]>0:
    results.append(-1)
else:
    results.append(1)

Список «результатов» - это столбец, который нужно добавить к M, поэтому выходные данные выглядят так (четвертое значение в каждой строке - результат условия), поэтому в основном матрица M объединяется с результатами по оси 1.

 # Just example values, not matching the rules above
 M=[[-0.5,0.5,-1,1],
   [1,-0.5,-1,-1],
   [-1,-1,-0.5,-1],
   [0.5,1-,1,1],
   [1,0.5,1,1]]

То, что я ищу, является более эффективным способом, чем выполнение операторов if / else для каждой строки матрицы. Я думал, что это можно решить с помощью умножения матриц ?! Цени любую помощь.

1 Ответ

0 голосов
/ 30 октября 2018

Прежде всего, из вашего описания кажется, что элемент не может быть нулевым, поэтому давайте предположим, что (без потери общности).

Существует 2**n возможных комбинаций знаков (3**n, если мы разрешаем нули), где n - количество столбцов. Их можно кодировать в векторе, который называется outcomes ниже.

Далее я покажу, как мы можем применить матричное умножение для решения этой проблемы.

Пусть M будет вашей входной матрицей:

In [36]: M
Out[36]:
array([[-0.5,  0.5, -1. ],
       [ 1. , -0.5, -1. ],
       [-1. , -1. , -0.5],
       [ 0.5,  1. , -1. ],
       [ 1. ,  0.5,  1. ]])

In [37]: m, n = M.shape

Теперь мы:

  • преобразовать M в двоичную матрицу, кодирующую знак каждого элемента;
  • считывать каждую строку результата, как если бы это было число с основанием 2.

Это дает для каждой строки M индекс соответствующего результата:

In [40]: outcome_index = np.matmul(M > 0, [2**i for i in range(n)])

In [41]: outcome_index
Out[41]: array([2, 1, 0, 3, 7])

Наконец, мы используем индекс для вычисления нового столбца:

In [42]: outcomes[outcome_index]
Out[42]: array([-1, -1,  1,  1, -1])

Добавление столбца к M оставлено в качестве упражнения для читателя. :)

P.S. Я использовал следующий outcomes вектор в этом примере:

In [43]: outcomes
Out[43]: array([ 1, -1, -1,  1,  1, -1, -1, -1])

P.P.S. Я только что заметил, что мой код считывает число base-2 справа налево вместо более естественного (для меня) слева направо. Это на самом деле не проблема, и ее легко изменить (также оставлено в качестве упражнения для читателя).

...