Нахождение ближайшего к значению в двух наборах данных с помощью цикла for - PullRequest
0 голосов
/ 22 января 2019

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

clear all; close all; clc;

data_a = [0; 15; 30; 45; 60; 75; 90];
data_b = randi([0, 90], [180, 101]);

[rows_a,cols_a] = size(data_a);  
[rows_b,cols_b] = size(data_b);

val1 = zeros(rows_a,cols_b);
ind1 = zeros(rows_a,cols_b);

for i = 1:cols_b
    for j = 1:rows_a
        [val1(j,i),ind1(j,i)] = min(abs(data_b(:,i) - data_a(j)));
    end
end

Поскольку я хотел бы отказаться от MATLAB (со временем у меня выйдет лицензия), я решил попробовать то же самое на python, но не повезло:

import numpy as np

data_a = np.array([[0],[15],[30],[45],[60],[75],[90]])
data_b = np.random.randint(91, size=(180, 101))

[rows_a,cols_a] = data_a.shape
[rows_b,cols_b] = data_b.shape

val1 = np.zeros((rows_a,cols_b))
ind1 = np.zeros((rows_a,cols_b))

for i in range(cols_b):
    for j in range(rows_a):
        [val1[j][i],ind1[j][i]] = np.amin(np.abs(data_b[:][i] - data_a[j]))

Код также выдал ошибку, которая не сделала меня мудрее:

TypeError: cannot unpack non-iterable numpy.int32 object

Если бы кто-нибудь мог найти время, чтобы объяснить, почему я невежественный дурак, указав, что я сделал неправильно, и что я мог сделать, чтобы это исправить, я был бы благодарен, поскольку это оказалось главным препятствием для моего прогресса.

Спасибо.

Ответы [ 2 ]

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

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

  1. Неправильное использование срезов для многомерных массивов: используйте [i, j] вместо [i][j]
  2. Неправильный перевод min() изMATLAB to NumPy: вы должны использовать и argmin(), и min().

Ваш фиксированный код будет выглядеть так:

import numpy as np

# just to make it reproducible in testing, can be commented for production
np.random.seed(0)

data_a = np.array([[0],[15],[30],[45],[60],[75],[90]])
data_b = np.random.randint(91, size=(180, 101))

[rows_a,cols_a] = data_a.shape
[rows_b,cols_b] = data_b.shape

val1 = np.zeros((rows_a,cols_b), dtype=int)
ind1 = np.zeros((rows_a,cols_b), dtype=int)

for i in range(cols_b):
    for j in range(rows_a):
        ind1[j, i] = np.argmin(np.abs(data_b[:, i] - data_a[j]))
        val1[j, i] = np.min(np.abs(data_b[:, i] - data_a[j])[ind1[j, i]])

Однако я бы здесь не использовал прямой цикли я бы хорошо использовал вещание:

import numpy as np

# just to make it reproducible in testing, can be commented for production
np.random.seed(0)

data_a = np.arange(0, 90 + 1, 15).reshape((-1, 1, 1))
data_b = np.random.randint(90 + 1, size=(1, 180, 101))

tmp_arr = np.abs(data_a.reshape(-1, 1, 1) - data_b.reshape(1, 180, -1), dtype=int)
min_idxs = np.argmin(tmp_arr, axis=1)
min_vals = np.min(tmp_arr, axis=1)
del tmp_arr  # you can delete this if you no longer need it

, где сейчас ind1 == min_idxs и val1 == min_vals, то есть:

print(np.all(min_idxs == ind1))
# True
print(np.all(min_vals == val1))
# True
0 голосов
/ 22 января 2019

Ваша ошибка связана с "[val1 [j] [i], ind1 [j] [i]] = (одно число)". Вы пытаетесь присвоить ему одно значение, которое не работает в python. Как насчет этого?

import numpy as np

data_a = np.array([[0],[15],[30],[45],[60],[75],[90]])
data_b = np.random.randint(91, size=(180,101))

[rows_a,cols_a] = data_a.shape
[rows_b,cols_b] = data_b.shape

val1 = np.zeros((rows_a,cols_b))
ind1 = np.zeros((rows_a,cols_b))

for i in range(cols_b):
    for j in range(rows_a):
        array = np.abs(data_b[:][i] - data_a[j])
        val = np.amin(array)
        val1[j][i] = val
        ind1[j][i] = np.where(val == array)[0][0]

Numpy amin не возвращает индекс, поэтому вам нужно вернуть его, используя np.where. В этом примере хранится не полный индекс, а только индекс первого вхождения в строке. Затем вы можете вытащить его, поскольку ваш порядок строк соответствует порядку столбцов в ind1 и data_b Так, например, на первой итерации.

In [2]: np.abs(data_b[:][0] - data_a[j0])
Out[2]: 
array([ 3, 31, 19, 53, 28, 81, 10, 11, 89, 15, 50, 22, 40, 81, 43, 29, 63,
       72, 22, 37, 54, 12, 19, 78, 85, 78, 37, 81, 41, 24, 29, 56, 37, 86,
       67,  7, 38, 27, 83, 81, 66, 32, 68, 29, 71, 26, 12, 27, 45, 58, 17,
       57, 54, 55, 23, 21, 46, 58, 75, 10, 25, 85, 70, 76,  0, 11, 19, 83,
       81, 68,  8, 63, 72, 48, 18, 29,  0, 47, 85, 79, 72, 85, 28, 28,  7,
       41, 80, 56, 59, 44, 82, 33, 42, 23, 42, 89, 58, 52, 44, 65, 65])

In [3]: np.amin(array)
Out[3]: 0

In [4]: val
Out[4]: 0

In [5]: np.where(val == array)[0][0]
Out[5]: 69

In [6]: data_b[0,69]
Out[6]: 0
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...