使用 accumarray 输出矩阵
Using accumarray to output a matrix
MATLAB 的 accumarray
在许多应用程序中具有令人难以置信的强大功能。我的问题是,应用于输入的 accumarray
函数具有三个输出,而 accumarray
只能处理标量输出。例如,我想做这样的事情:
subs = [1;2;4;2;4;5];
vals = [1;1;1;2;5;1];
accumarray(subs, vals, [], @(x)[min(x),mean(x),max(x)],0)
并有 accumarray
return:
1.0000 1.0000 0 1.0000 1.0000
1.0000 1.5000 0 3.0000 1.0000
1.0000 2.0000 0 5.0000 1.0000
我想我可以 运行 accumarray
三次,但是我的函数很慢, 运行ning accumarray
once 会比 [=26 快得多=]宁三遍。我刚刚在这里冲洗过吗?
您可以作弊使匿名函数输出一个 元胞数组 而不是单个值。这样,accumarray
将为您提供一个矩阵元胞数组。完成后,您可以将所有矩阵连接成一个矩阵。请注意,您建议的匿名函数将 min
、max
和 mean
作为行向量,但您的预期结果是 列 向量。因此,我已将其转置到您的匿名函数中。
我们必须考虑的陷阱是填充值。您指定的填充值需要是标量。因此,您可以通过省略它来作弊,但是您的输出现在将在单元格中包含空矩阵,而不是结果行填充 0。解决此问题的一种方法是找到所有空单元格,将它们替换为一排零,然后在完成后将它们拼凑在一起。要确定 accumarray
输出的哪些行将为空,您可以使用 cellfun
combined with isempty
以便我们可以查看结果中的哪些元素为空。一种更简洁的方法是首先预分配 zeros
的矩阵,然后仅填充与 accumarray
输出中非空位置对应的行以完成它:
subs = [1;2;4;2;4;5];
vals = [1;1;1;2;5;1];
out = accumarray(subs, vals, [], @(x){[min(x),mean(x),max(x)].'});
ind_empty = cellfun('isempty', out);
out_final = zeros(3, numel(out));
out_final(:, ~ind_empty) = cat(2, out{:});
注意 cat
which is concatenating matrices together in a specified dimension. Doing out{:}
produces what is known as a comma-separated list 的使用,因此它相当于获取 accumarray
输出的每一列并将它们作为单独的参数放入 cat
中,这样我们最终会拼凑所有的列一起组成一个矩阵,但我以这样的方式切入输出,我们只填充那些不为空的位置。
根据您的测试输入,我会匹配您得到的结果:
>> out_final
out_final =
1.0000 1.0000 0 1.0000 1.0000
1.0000 1.5000 0 3.0000 1.0000
1.0000 2.0000 0 5.0000 1.0000
但是,老实说 - 如果您确定只有三个值可以合并到 accumarray
,简单地调用它三次然后连接所有内容可能会更快当你完成时。我会争辩说它更具可读性,并且可以非常清楚地说明您在做什么。按照我对上面的元胞数组所做的方式进行操作需要您真正了解 MATLAB 的工作原理。
MATLAB 的 accumarray
在许多应用程序中具有令人难以置信的强大功能。我的问题是,应用于输入的 accumarray
函数具有三个输出,而 accumarray
只能处理标量输出。例如,我想做这样的事情:
subs = [1;2;4;2;4;5];
vals = [1;1;1;2;5;1];
accumarray(subs, vals, [], @(x)[min(x),mean(x),max(x)],0)
并有 accumarray
return:
1.0000 1.0000 0 1.0000 1.0000
1.0000 1.5000 0 3.0000 1.0000
1.0000 2.0000 0 5.0000 1.0000
我想我可以 运行 accumarray
三次,但是我的函数很慢, 运行ning accumarray
once 会比 [=26 快得多=]宁三遍。我刚刚在这里冲洗过吗?
您可以作弊使匿名函数输出一个 元胞数组 而不是单个值。这样,accumarray
将为您提供一个矩阵元胞数组。完成后,您可以将所有矩阵连接成一个矩阵。请注意,您建议的匿名函数将 min
、max
和 mean
作为行向量,但您的预期结果是 列 向量。因此,我已将其转置到您的匿名函数中。
我们必须考虑的陷阱是填充值。您指定的填充值需要是标量。因此,您可以通过省略它来作弊,但是您的输出现在将在单元格中包含空矩阵,而不是结果行填充 0。解决此问题的一种方法是找到所有空单元格,将它们替换为一排零,然后在完成后将它们拼凑在一起。要确定 accumarray
输出的哪些行将为空,您可以使用 cellfun
combined with isempty
以便我们可以查看结果中的哪些元素为空。一种更简洁的方法是首先预分配 zeros
的矩阵,然后仅填充与 accumarray
输出中非空位置对应的行以完成它:
subs = [1;2;4;2;4;5];
vals = [1;1;1;2;5;1];
out = accumarray(subs, vals, [], @(x){[min(x),mean(x),max(x)].'});
ind_empty = cellfun('isempty', out);
out_final = zeros(3, numel(out));
out_final(:, ~ind_empty) = cat(2, out{:});
注意 cat
which is concatenating matrices together in a specified dimension. Doing out{:}
produces what is known as a comma-separated list 的使用,因此它相当于获取 accumarray
输出的每一列并将它们作为单独的参数放入 cat
中,这样我们最终会拼凑所有的列一起组成一个矩阵,但我以这样的方式切入输出,我们只填充那些不为空的位置。
根据您的测试输入,我会匹配您得到的结果:
>> out_final
out_final =
1.0000 1.0000 0 1.0000 1.0000
1.0000 1.5000 0 3.0000 1.0000
1.0000 2.0000 0 5.0000 1.0000
但是,老实说 - 如果您确定只有三个值可以合并到 accumarray
,简单地调用它三次然后连接所有内容可能会更快当你完成时。我会争辩说它更具可读性,并且可以非常清楚地说明您在做什么。按照我对上面的元胞数组所做的方式进行操作需要您真正了解 MATLAB 的工作原理。