使用for循环在两个数据集中找到最接近值的值

时间:2019-01-22 19:04:10

标签: python matlab numpy

在MATLAB中,我可以使用以下代码找到与data_a中的值最接近的data_b中的值,以及指示它们出现在矩阵中哪个位置的索引,以及这些代码:

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

如果任何人都可以通过指出我做错了什么以及我可以做些什么来弥补我的愚昧无知,我将不胜感激,因为事实证明这已成为我前进的主要障碍。 / p>

谢谢。

2 个答案:

答案 0 :(得分:1)

我认为您面临两个问题:

  1. 对多维数组切片使用不正确:使用[i, j]代替[i][j]
  2. min()从MATLAB到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_idxsval1 == min_vals,即:

print(np.all(min_idxs == ind1))
# True
print(np.all(min_vals == val1))
# True

答案 1 :(得分:0)

您的错误与“ [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