Python 使用for循环查找两个数据集中最接近的值
在MATLAB中,我能够通过以下代码识别数据_b中与数据_a中的值最接近的值,以及指示它们出现在矩阵中哪个位置的索引:Python 使用for循环查找两个数据集中最接近的值,python,matlab,numpy,Python,Matlab,Numpy,在MATLAB中,我能够通过以下代码识别数据_b中与数据_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
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
如果有人能抽出时间来解释为什么我是一个无知的傻瓜,指出我做错了什么,以及我能做些什么来纠正它,我将不胜感激,因为这已经证明是我进步的主要障碍
谢谢。您的错误与“[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
我认为你们面临两个问题:
[i,j]
而不是[i][j]
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_idxs
和val1==min_vals
,即:
print(np.all(min_idxs == ind1))
# True
print(np.all(min_vals == val1))
# True
我想知道你的MATLAB代码是如何工作的。
val1
和ind1
的维度是不同的,您仍然能够在同一for循环中使用i和j索引?您不必在MATLAB中将所有内容都分组到方括号中,您知道。仅当您有多个元素(如在数据中),但不在单个元素周围…Bazingaa时,它们似乎是相同的7x101矩阵(尽管我的知识有限,可能误解了您的评论)。我知道,阿德里安,由于懒惰,我把它从python复制到了MATLAB。如果您发现它有误导性,我很抱歉。您是否有理由希望数据\u a
具有这种形状(例如(7,1)
)?您是否可以提供一个较小尺寸的输入/输出示例?(我假设data_a
只能有两点,而且data_b
可以减少到较少的元素,以便进行测试)谢谢您的帮助。不幸的是(这很可能是由于我的无能和普遍的愚蠢),我无法使它像我想象的那样工作(以及它在MATLAB中的工作方式)。最后我想得到一个7x101矩阵,其中包含最接近参考值(data_a)的数据_b值。非常感谢,norok2!杰出的这正是我一直尝试(但失败)去做的!如果你不介意我问(有点离题),但是有没有办法列出所有出现数字(data\u a
)的data\u b
位置,而不仅仅是第一次出现?你的解决方案正是我所追求的,而另一个只是一种好奇心,以备将来参考。@顽皮的波浪我不知道有一个函数可以找到所有的全局最大值/最小值,我想这与你可能想要得到一致维度的结果这一事实有关(如果一个序列中有2个最小值,另一个序列中有3个最小值,那么结果的形状应该是什么?)无论如何,如果你有一个数组arr
,你知道它的最小值min\u arr
,你可以得到一个掩码,通过arr==min\u arr
选择所有这些值来获得你将使用的索引(arr==min\u-arr)
。我理解——我对这一切都很陌生,所以当有经验的用户让我明白过来时,这会有很大帮助。再次感谢,@norok2.:)