要清楚以下不是我原来的问题,它的数据要大得多,而且这个代码是在更大的应用程序和代码库的上下文中。我已经将我的工作简化为最简单的例子,现在是玩具或教学大小,以便清晰,开发和单元测试,因为这对于这些目的以及在stackexchange上共享有很大帮助。我在R中有经验,但在八度音程中没有经验(Matlab)。这是octave版本4.0.0的代码。我似乎停留在翻译组计算,如R的tapply()或by(),以及编写和调用用户定义的函数(加上一些额外的处理,而不是那些内置函数),但现在用八度语言编写。
起始状态是一个数组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列中找到min统计信息,返回存储在同一行第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是组内行的索引,但不是数组中的行,只要我稍后进行计算以将索引从group-relative转换为global-relative,并且在那里读取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
请注意,y是我需要的所有min(),因为它是感兴趣的行的索引。
>> accumarray(a(:,1), a(:,3), [], @([~,y]=min([],[],1)))
parse error:
syntax error
请注意,对于某种语法,我需要在其第一个参数中传递给min(),该值由accumarray的参数1和2确定。
我最终需要在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无法访问。现在我该怎么办?谢谢你的阅读。
答案 0 :(得分:1)
在MATLAB / Octave中声明函数时,无法访问在作用域外声明的任何变量(默认情况下)。这意味着即使您有a
的声明,当您创建该函数时,a
也无法在函数范围内访问。
您可以做的是修改ccen
,以便为函数提供a
,以便在调用函数时可以访问变量。之后,在致电ccen
时围绕您对accumarray
的来电包裹匿名函数。然而,匿名函数 do 可以捕获未明确声明为函数输入变量的变量范围:
首先:
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