具有多个输出的 Matlab `rowfun` 函数:可以安全地假定行顺序吗?
Matlab `rowfun` function with multiple outputs: Safe to assume row order?
我尝试为 rowfun
提供一个函数,该函数 returns 多行输出,与输入的高度相同。 似乎 可以正常工作。
% Example table with 2-column-array as a single data field
x = table( [1;1;2;2] , [[2;2;1;1] [2;1;2;1]] , ...
'VariableNames' , {'idx' 'Field2columns'} )
x = idx Field2columns
___ _____________
1 2 2
1 2 1
2 1 2
2 1 1
% Example anonymous function takes all rows with same idx value and
% reverse their row order
y = rowfun( @(z) z(end:-1:1,:) , x , 'Input','Field2columns' , ...
'Grouping','idx' , 'OutputVar','OutVar' )
y = idx GroupCount OutVar
___ __________ ______
1 1 2 2 1
1_1 1 2 2 2
2 2 2 1 1
2_1 2 2 1 2
% Append the generated data to original table
[ x y(:,{'OutVar'}) ]
ans = idx Field2columns OutVar
___ _____________ ______
1 1 2 2 2 1
1_1 1 2 1 2 2
2 2 1 2 1 1
2_1 2 1 1 1 2
这使得代码非常高效。否则我将不得不遍历 x.idx
的所有不同值,为每个值提取 x
的匹配行,生成行反转子集并编译结果。
我唯一担心的是我假设匿名函数输出的行顺序将保持不变,并且每一行将与 table x
中的相应行对齐。例如,如果idx=7,那么x
中idx=7的第N行在应用于x(x.idx==7,:)
.[=18时,将在匿名函数输出中的第N行右侧追加=]
rowfun
文档不处理第一个参数表示 returns 多行输出的函数的情况。我只能依赖观察到的行为。利用这种行为来简化我的代码是明智的,还是依赖这种未记录的行为是不好的做法,例如,可能不会涵盖极端情况,并且 TMW 没有义务在未来保持当前行为?
rowfun
的 documentation,在 'GroupingVariables'
下说:
The output, B, contains one row for each group.
因此,如果您每组获得不止一行,那么您肯定是在涉足无证水域。未来的版本可能会引发您的代码错误。
关于函数输入行的顺序:我建议您向 MathWorks 询问具有相同分组变量的行的顺序。一种方法是转到文档页面的底部,select 星级,然后在文本框中说文档不完整,因为它没有指定此选项时的行顺序给出。文档人员喜欢文档的全面和完整,他们可能会通过完成文档来回答这个问题。
如果您想留在记录的区域中,可以使用非常方便的 splitapply
。要处理输出中的多行,您可以将它们放在一个单元格中,然后将其转换为 table:
y = splitapply(@(z) {z(end:-1:1,:)},x.Field2columns,x.idx) % note the {...} in the function
[x table(cell2mat(y),'VariableNames',{'OutVar'})] % this is like: [x y(:,{'OutVar'})]
我想这会降低效率,但它可以使您的代码保持在函数的记录行为范围内,而无需使用循环。
我尝试为 rowfun
提供一个函数,该函数 returns 多行输出,与输入的高度相同。 似乎 可以正常工作。
% Example table with 2-column-array as a single data field
x = table( [1;1;2;2] , [[2;2;1;1] [2;1;2;1]] , ...
'VariableNames' , {'idx' 'Field2columns'} )
x = idx Field2columns
___ _____________
1 2 2
1 2 1
2 1 2
2 1 1
% Example anonymous function takes all rows with same idx value and
% reverse their row order
y = rowfun( @(z) z(end:-1:1,:) , x , 'Input','Field2columns' , ...
'Grouping','idx' , 'OutputVar','OutVar' )
y = idx GroupCount OutVar
___ __________ ______
1 1 2 2 1
1_1 1 2 2 2
2 2 2 1 1
2_1 2 2 1 2
% Append the generated data to original table
[ x y(:,{'OutVar'}) ]
ans = idx Field2columns OutVar
___ _____________ ______
1 1 2 2 2 1
1_1 1 2 1 2 2
2 2 1 2 1 1
2_1 2 1 1 1 2
这使得代码非常高效。否则我将不得不遍历 x.idx
的所有不同值,为每个值提取 x
的匹配行,生成行反转子集并编译结果。
我唯一担心的是我假设匿名函数输出的行顺序将保持不变,并且每一行将与 table x
中的相应行对齐。例如,如果idx=7,那么x
中idx=7的第N行在应用于x(x.idx==7,:)
.[=18时,将在匿名函数输出中的第N行右侧追加=]
rowfun
文档不处理第一个参数表示 returns 多行输出的函数的情况。我只能依赖观察到的行为。利用这种行为来简化我的代码是明智的,还是依赖这种未记录的行为是不好的做法,例如,可能不会涵盖极端情况,并且 TMW 没有义务在未来保持当前行为?
rowfun
的 documentation,在 'GroupingVariables'
下说:
The output, B, contains one row for each group.
因此,如果您每组获得不止一行,那么您肯定是在涉足无证水域。未来的版本可能会引发您的代码错误。
关于函数输入行的顺序:我建议您向 MathWorks 询问具有相同分组变量的行的顺序。一种方法是转到文档页面的底部,select 星级,然后在文本框中说文档不完整,因为它没有指定此选项时的行顺序给出。文档人员喜欢文档的全面和完整,他们可能会通过完成文档来回答这个问题。
如果您想留在记录的区域中,可以使用非常方便的 splitapply
。要处理输出中的多行,您可以将它们放在一个单元格中,然后将其转换为 table:
y = splitapply(@(z) {z(end:-1:1,:)},x.Field2columns,x.idx) % note the {...} in the function
[x table(cell2mat(y),'VariableNames',{'OutVar'})] % this is like: [x y(:,{'OutVar'})]
我想这会降低效率,但它可以使您的代码保持在函数的记录行为范围内,而无需使用循环。