使用 "find" 命令累加值 "without for loops"

Using the "find" command to accumulate values "without for loops"

我将使用 find 从一个矩阵(名为 lag)中获取索引,然后从另一个矩阵(H)中对它们的相应值求和。这将需要一个 for 循环。 (矩阵是二维的。)

(此处使用max来暗示一个通用示例)

D=zeros(max, 1)
for j = 1:max
    ind = find(lag==j)
    D(j) = sum(H(ind))
end

这是一个4分的例子。点位于 (1,1)、(1,2)、(2,1)、(2,2)。这是地统计学方法的一部分。 H 中计算了所有点之间的距离。 lagsH 但向下舍入然后加 1 以将距离与其最接近的整数相关联(称为滞后的分类)。我现在想将每个 lag 的总距离加到矢量 D.

lag (4x4) - 存储一般滞后间隔

1  2  2  2
2  1  2  2
2  2  1  2
2  2  2  1

H (4x4) - 存储点之间的距离

0   1   1   1.414
1   0   1.414   1
1   1.414   0   1
1.414   1   1   0

我可以在没有 for 循环的情况下执行此操作吗?

没有 for 循环就没有好的方法,但是你可以不使用 find.

D = zeros(N, 1)
for j = 1:N
   D(j) = sum(sum((lag == j).*H));
end

lag == j 的结果将是一个 4x4(或更确切地说 NxN)布尔值矩阵,这样 (lag == j).*H 将保留每个滞后的距离,但所有其他元素都为零。对 (lag == j).*H 中的所有元素求和将为 D(j).

提供相同的答案

请注意,我已将 max 切换为 N,因为 max 是内置的 MATLAB 函数。

您可以使用

ulag = unique(lag); %contains [1 2]
D = arrayfun(@(l)sum(H(lag==l)),ulag);

unique(lag) 会将 lag 提取为唯一值,在您的小示例中 [1 2]。然后 arrayfun 将遍历数组 ulag,并且对于每个元素 l 它将执行 sum(H(lag==l)),这正是您想要的:对 [=20= 中的那些元素求和] lag 中对应的元素等于 l。请注意,这仅在 lag 包含整数时才有效,否则 unique 可能由于机器精度而找不到相同的元素(但从你的问题中我了解到它可能本质上是一个整数)。

另请注意,上面两行也可以写成一条:

D = arrayfun(@(l)sum(H(lag==l)),unique(lag));

我只是觉得分开后可能更容易消化

还要注意,上面利用了 lag 的值从 1 开始到最大值,没有间隙。如果不是这种情况,那么你应该做类似

的事情
D(unique(lag)) = arrayfun(@(l)sum(H(lag==l)),unique(lag));

但在这种情况下,您必须确保 lag 不包含非正值。

这很容易用accumarray完成:

D = accumarray(lag(:), H(:));

这会为由第一个参数(lag 线性化为列向量)的值定义的每个组累积(求和)第二个参数的值(H 线性化为列向量) .