2

我想逐个元素地比较矩阵并找到矩阵的最大值,就像我有三个 3x3 矩阵

tdata = {{{1, 5, 1}, {7, 4, 2}, {2, 4, 3}}, {{2, 0, 8}, {9, 8, 2}, {2,
 3, 0}}, {{2, 2, 9}, {10, 9, 5}, {9, 3, 3}}}

然后通过使用

MapThread[Max, tdata, 2] // MatrixForm

我可以得到正确的结果。

{{2, 5, 9}, {10, 9, 5}, {9, 4, 3}}

但是,当矩阵是复数矩阵时,Max 函数不起作用。例如,

tdata = {{{0.323031 + 5.23687 I, 8.92856 + 1.31365 I},
{9.94387 + 3.04104 I, 8.72483 + 2.5648 I}},
{{5.96575 + 9.2521 I,  8.58461 + 2.56753 I},
{0.902715 + 3.75791 I, 4.06809 + 8.61552 I}},
{{9.36592 + 1.17263 I, 9.74628 + 2.22183 I},
{4.61866 + 4.61158 I, 9.0791 + 2.50036 I}}}

我试图为复杂的矩阵实现一个新的 Max 函数,但它不起作用。这是一个演示,

complexMax[lis_] := Module[{abs = Abs[lis]}, Take[lis, Position[abs, Max[abs]][[1]]]]

然后

MapThread[complexMax, tdata, 2]

结果就像

{{complexMax[0.323031 + 5.23687 I, 5.96575 + 9.2521 I, 9.36592 + 1.17263 I], 
 complexMax[8.92856 + 1.31365 I, 8.58461 + 2.56753 I, 9.74628 + 2.22183 I]}, 
{complexMax[9.94387 + 3.04104 I, 0.902715 + 3.75791 I, 4.61866 + 4.61158 I], 
 complexMax[8.72483 + 2.5648 I, 4.06809 + 8.61552 I, 9.0791 + 2.50036 I]}}

有什么想法可以解决这个问题吗?

4

3 回答 3

2

我认为这就是你想要的:

MapThread[Last@SortBy[{##}, Abs] &, tdata, 2] // MatrixForm

(* {{5.96575 + 9.2521 I, 9.74628 + 2.22183 I}, {9.94387 + 3.04104 I, 4.06809 + 8.61552 I}} *)

FWIW 按规范顺序对复数进行排序,(实部在前)

MapThread[Last@Sort[{##}] &, tdata, 2] // MatrixForm

(* {{9.36592 + 1.17263 I, 9.74628 + 2.22183 I}, {9.94387 + 3.04104 I, 9.0791 + 2.50036 I}} *)

请注意,如果您这样做,您的方法也适用:

 MapThread[complexMax[{##}] &, tdata, 2]

诀窍是传递Mapthread给你的函数的参数是一个序列,而不是一个列表。

于 2013-08-05T18:01:39.123 回答
2

您当前代码的问题在于,使用MapThread导致complexMax调用的结果不是使用作为列表的单个参数(即complexMax[{elem1, elem2, elem3...}]),而是使用多个参数(即complexMax[elem1, elem2, elem3])。

您可以通过将参数声明为不是单个表达式(lis_带单个下划线)而是声明为一系列表达式来纠正此问题:lis__带双下划线。

但是,进行此更正会导致另一个问题 -Abs需要一个列表作为输入,就像Take. 所以你需要lis在几个地方用括号括起来。

最后,看起来你最后需要一个额外[[1]]的。

complexMax[lis__] := Module[{abs = Abs[{lis}]},
  Take[{lis}, Position[abs, Max[abs]][[1]]][[1]]] 

MapThread[complexMax, tdata, 2]

结果

{{5.96575 + 9.2521 I, 9.74628 + 2.22183 I}, {9.94387 + 3.04104 I, 
  4.06809 + 8.61552 I}}
于 2013-08-05T18:16:16.240 回答
1

现在有一个专门用于Mathematica的 StackExchange 站点:https ://mathematica.stackexchange.com/——请在那里提出您未来的问题。


正如 latkin 已经解释的那样,如果要使用 max 函数,它需要接受多个参数,如MapThread. 您可以使用第二种模式编写函数来处理这两种形式,例如cMax[ns__] := cMax[{ns}].

Position比现在快Ordering

cMax[ns__] := cMax[{ns}]

cMax[lis_List] := lis ~Extract~ Ordering[Abs[lis], -1]

现在:

MapThread[cMax, tdata, 2]
{{5.96575 + 9.2521 I, 9.74628 + 2.22183 I},
 {9.94387 + 3.04104 I, 4.06809 + 8.61552 I}}

但是,在处理打包数据时,不使用会更快MapThread,这会导致解包,而是通过使用将数字保留在列表中Transpose

Map[cMax, Transpose[tdata, {3, 1, 2}], {2}]
{{5.96575 + 9.2521 I, 9.74628 + 2.22183 I},
 {9.94387 + 3.04104 I, 4.06809 + 8.61552 I}}

时间:

cd = RandomComplex[9 + 9 I, {15000, 7, 7}];

MapThread[Last@SortBy[{##}, Abs] &, cd, 2] // Timing // First

MapThread[cMax, cd, 2]                     // Timing // First

Map[cMax, Transpose[cd, {3, 1, 2}], {2}]   // Timing // First

0.562

0.483

0.0156

于 2013-08-05T20:46:28.367 回答