gpt4 book ai didi

arrays - 使用 accumarray 和用户定义函数返回第三列值的 Octave 组统计计算

转载 作者:行者123 更新时间:2023-12-01 14:45:35 26 4
gpt4 key购买 nike

要明确的是,以下不是我的原始问题,它具有更大的数据,并且此代码位于更大的应用程序和代码库的上下文中。我已将我的工作缩减为最简单的示例,为了清晰和开发和单元测试,现在只是玩具或教学大小,因为这对这些目的以及在 stackexchange 上共享有很大帮助。我在 R 方面有经验,但在 Octave (Matlab)方面没有经验。这是 Octave 版本 4.0.0 的代码。我似乎坚持翻译组计算,如 R 的 tapply() 或 by() 以及编写和调用用户定义的函数(加上比那些内置的一些额外处理),但现在用 Octave 语言编写。

起始状态是一个数组a,如图所示:

a = [5 1 8 0; 2 1 9 0; 2 3 3 0; 5 3 9 0]

a =

5 1 8 0
2 1 9 0
2 3 3 0
5 3 9 0

我需要做的过程本质上就是这样:按第1列分组,找到第3列的最小统计量,返回同一行第2列存储的值,并将该值写入第4列。我要没有要使用的可选包。内置的 accumarray 和 min 函数让我非常接近,但我还没有找到所需的语法。 Matlab 似乎有许多版本的参数传递语法在不同版本上开发,请注意我的代码需要在 Octave 4.0.0 中运行。

所需的最终状态与数组 a 相同,但第 4 列更新如下所示:

a =

5 1 8 1
2 1 9 3
2 3 3 3
5 3 9 1

我最好的几个未遂代码片段和我所有失败尝试中最有趣的事情(没有显示,因为有很多页面的尝试都不起作用)是:

[x,y] = min(a(a(:,1)==5,3),[],1)
x = 8
y = 1

请注意,y 是组内行的索引,但不是数组内的行,这很好,只要我稍后进行计算以将索引从组相关转换为全局相关,并且在其中读取 a(y,2) 的值,这是每一行的正确答案值。

>> [x,y] = min(a(a(:,1)==2,3),[],1)
x = 3
y = 2
>> [~,y] = min(a(a(:,1)==2,3),[],1);
>> y
y = 2

请注意,我只需要 min() 中的 y,因为它是感兴趣的行的索引。

>> accumarray(a(:,1), a(:,3), [], @([~,y]=min([],[],1)))
parse error:

syntax error

请注意,使用某种语法,我需要在其第一个参数中将由 accumarray 的参数 1 和 2 确定的值组传递给 min()。

在 min() 返回行索引 y 之后,我最终需要在组计算中发生这样的事情:

a(y,4) = a(y,2); % y is the desired row index found by min() within each group

因此,我尝试编写一个以可能更简单的语法命名的函数:

>> function idx = ccen(d)
[~,y]=min(d,[],1);
idx=a(y,2);
end
>> accumarray(a(:,1), a(:,3), [], @ccen)
error: 'a' undefined near line 3 column 5
error: called from
ccen at line 3 column 4
accumarray at line 345 column 14

在我看来,令我惊讶的是,函数 ccen 无法访问 a。现在我该怎么办?感谢您的阅读。

最佳答案

在 MATLAB/Octave 中声明函数时,在范围外声明的任何变量(默认情况下)不可访问。这意味着即使您有 a 的声明,当您创建该函数时,a 在该函数的范围内也是不可访问的。

您可以做的是修改 ccen 以便将 a 提供给函数,以便它可以在调用函数时访问变量。之后,在调用 accumarray 时,在对 ccen 的调用周围包装一个匿名函数。然而,匿名函数确实可以捕获未明确声明为函数输入变量的变量范围:

那么首先:

function idx = ccen(a, d) %// Change
[~,y]=min(d,[],1);
idx=a(y,2);
end

现在……

out = accumarray(a(:,1), a(:,3), [], @(x) ccen(a,x)); %// Change last parameter

此调用是可以接受的,因为匿名函数在创建时正在捕获 a。请注意匿名函数中的 x 是如何从 accumarray 调用中通过管道输入的。您只需将其作为第二个参数转发给 ccen 并保持 a 不变。这不会改变函数的运行方式....它只是解决范围问题。

我在 Octave 中得到以下内容:

octave:10> a = [5 1 8 0; 2 1 9 0; 2 3 3 0; 5 3 9 0]
a =

5 1 8 0
2 1 9 0
2 3 3 0
5 3 9 0

octave:11> function idx = ccen(a,d)
> [~,y]=min(d,[],1);
> idx=a(y,2);
> end
octave:12> out = accumarray(a(:,1), a(:,3), [], @(x) ccen(a,x))
out =

0
1
0
0
1

关于arrays - 使用 accumarray 和用户定义函数返回第三列值的 Octave 组统计计算,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34952162/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com